Bash: Succinct way to loop over lines from stdin or command line arguments?
Clash Royale CLAN TAG#URR8PPP
up vote
1
down vote
favorite
I've got a bash script I'd like to loop over the lines in stdin, or loop over each argument passed in.
Is there a clean way to write this so I don't have to have 2 loops?
#!/bin/bash
# if we have command line args...
if [ -t 0 ]
then
# loop over arguments
for arg in "$@"
do
# process each argument
done
else
# loop over lines from stdin
while IFS= read -r line; do
# process each line
done
fi
EDIT: I'm looking for a generic solution that just uses a single loop, as I find I want to do this quite often, but have always wrote out 2 loops and then called a function instead. So maybe something that turns stdin into an array, so I could use a single loop instead?
bash
add a comment |Â
up vote
1
down vote
favorite
I've got a bash script I'd like to loop over the lines in stdin, or loop over each argument passed in.
Is there a clean way to write this so I don't have to have 2 loops?
#!/bin/bash
# if we have command line args...
if [ -t 0 ]
then
# loop over arguments
for arg in "$@"
do
# process each argument
done
else
# loop over lines from stdin
while IFS= read -r line; do
# process each line
done
fi
EDIT: I'm looking for a generic solution that just uses a single loop, as I find I want to do this quite often, but have always wrote out 2 loops and then called a function instead. So maybe something that turns stdin into an array, so I could use a single loop instead?
bash
1
What are you actually trying to accomplish ? Sounds like a typical XY question...
â don_crissti
Mar 23 at 13:51
What's the problem you're trying to solve? What kind of processing needs to happen in the loop?
â Kusalananda
Mar 23 at 14:15
thanks for the feedback! I write lots of little bash scripts that I like to be able to accepts args from the command line, or from stdin. The particular script i'm writing now is one that will concatenate arguments using a delimiter, so I can write bothcat /tmp/it | concat
andconcat a b c
and it'd join these arguments together in both cases, trimming each arg and putting a comma between items. e.g.a,b,c
.
â Brad Parks
Mar 23 at 14:18
add a comment |Â
up vote
1
down vote
favorite
up vote
1
down vote
favorite
I've got a bash script I'd like to loop over the lines in stdin, or loop over each argument passed in.
Is there a clean way to write this so I don't have to have 2 loops?
#!/bin/bash
# if we have command line args...
if [ -t 0 ]
then
# loop over arguments
for arg in "$@"
do
# process each argument
done
else
# loop over lines from stdin
while IFS= read -r line; do
# process each line
done
fi
EDIT: I'm looking for a generic solution that just uses a single loop, as I find I want to do this quite often, but have always wrote out 2 loops and then called a function instead. So maybe something that turns stdin into an array, so I could use a single loop instead?
bash
I've got a bash script I'd like to loop over the lines in stdin, or loop over each argument passed in.
Is there a clean way to write this so I don't have to have 2 loops?
#!/bin/bash
# if we have command line args...
if [ -t 0 ]
then
# loop over arguments
for arg in "$@"
do
# process each argument
done
else
# loop over lines from stdin
while IFS= read -r line; do
# process each line
done
fi
EDIT: I'm looking for a generic solution that just uses a single loop, as I find I want to do this quite often, but have always wrote out 2 loops and then called a function instead. So maybe something that turns stdin into an array, so I could use a single loop instead?
bash
edited Mar 23 at 14:37
asked Mar 23 at 13:35
Brad Parks
400321
400321
1
What are you actually trying to accomplish ? Sounds like a typical XY question...
â don_crissti
Mar 23 at 13:51
What's the problem you're trying to solve? What kind of processing needs to happen in the loop?
â Kusalananda
Mar 23 at 14:15
thanks for the feedback! I write lots of little bash scripts that I like to be able to accepts args from the command line, or from stdin. The particular script i'm writing now is one that will concatenate arguments using a delimiter, so I can write bothcat /tmp/it | concat
andconcat a b c
and it'd join these arguments together in both cases, trimming each arg and putting a comma between items. e.g.a,b,c
.
â Brad Parks
Mar 23 at 14:18
add a comment |Â
1
What are you actually trying to accomplish ? Sounds like a typical XY question...
â don_crissti
Mar 23 at 13:51
What's the problem you're trying to solve? What kind of processing needs to happen in the loop?
â Kusalananda
Mar 23 at 14:15
thanks for the feedback! I write lots of little bash scripts that I like to be able to accepts args from the command line, or from stdin. The particular script i'm writing now is one that will concatenate arguments using a delimiter, so I can write bothcat /tmp/it | concat
andconcat a b c
and it'd join these arguments together in both cases, trimming each arg and putting a comma between items. e.g.a,b,c
.
â Brad Parks
Mar 23 at 14:18
1
1
What are you actually trying to accomplish ? Sounds like a typical XY question...
â don_crissti
Mar 23 at 13:51
What are you actually trying to accomplish ? Sounds like a typical XY question...
â don_crissti
Mar 23 at 13:51
What's the problem you're trying to solve? What kind of processing needs to happen in the loop?
â Kusalananda
Mar 23 at 14:15
What's the problem you're trying to solve? What kind of processing needs to happen in the loop?
â Kusalananda
Mar 23 at 14:15
thanks for the feedback! I write lots of little bash scripts that I like to be able to accepts args from the command line, or from stdin. The particular script i'm writing now is one that will concatenate arguments using a delimiter, so I can write both
cat /tmp/it | concat
and concat a b c
and it'd join these arguments together in both cases, trimming each arg and putting a comma between items. e.g. a,b,c
.â Brad Parks
Mar 23 at 14:18
thanks for the feedback! I write lots of little bash scripts that I like to be able to accepts args from the command line, or from stdin. The particular script i'm writing now is one that will concatenate arguments using a delimiter, so I can write both
cat /tmp/it | concat
and concat a b c
and it'd join these arguments together in both cases, trimming each arg and putting a comma between items. e.g. a,b,c
.â Brad Parks
Mar 23 at 14:18
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
2
down vote
accepted
Create data for your while read
loop:
#!/bin/sh
if [ "$#" -gt 0 ]; then
# We have command line arguments.
# Output them with newlines in-between.
printf '%sn' "$@"
else
# No command line arguments.
# Just pass stdin on.
cat
fi |
while IFS= read -r; do
printf 'Got "%s"n' "$REPLY"
done
Note that your concat
example can be done with the while read
loop replaced by tr 'n' ','
or similar.
Also, the -t
test says nothing about whether you have command line arguments or not.
Alternatively, to process both command line arguments and standard input (in that order):
#!/bin/sh
if [ "$#" -gt 0 ]; then
# We have command line arguments.
# Output them with newlines in-between.
printf '%sn' "$@"
fi
if [ ! -t 0 ]; then
# Pass stdin on.
cat
fi
|
while IFS= read -r; do
printf 'Got "%s"n' "$REPLY"
done
Or, using short-cut notation that some people seems to like:
#!/bin/sh
[ "$#" -gt 0 ] && printf '%sn' "$@"
[ ! -t 0 ] && cat
|
while IFS= read -r; do
printf 'Got "%s"n' "$REPLY"
done
Note that that changes the behaviour if there are arguments that contain newline characters.
â Stéphane Chazelas
Mar 23 at 15:04
@StéphaneChazelas Yes, command line arguments with literal newlines in them will be broken up into multiple items when they arrive at the loop.
â Kusalananda
Mar 23 at 15:07
add a comment |Â
up vote
1
down vote
With bash
specifically, you could do:
if [ -t 0 ]; then
args=("$@")
else
readarray -t args
fi
for i in "$args[@]"; do
...
done
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
Create data for your while read
loop:
#!/bin/sh
if [ "$#" -gt 0 ]; then
# We have command line arguments.
# Output them with newlines in-between.
printf '%sn' "$@"
else
# No command line arguments.
# Just pass stdin on.
cat
fi |
while IFS= read -r; do
printf 'Got "%s"n' "$REPLY"
done
Note that your concat
example can be done with the while read
loop replaced by tr 'n' ','
or similar.
Also, the -t
test says nothing about whether you have command line arguments or not.
Alternatively, to process both command line arguments and standard input (in that order):
#!/bin/sh
if [ "$#" -gt 0 ]; then
# We have command line arguments.
# Output them with newlines in-between.
printf '%sn' "$@"
fi
if [ ! -t 0 ]; then
# Pass stdin on.
cat
fi
|
while IFS= read -r; do
printf 'Got "%s"n' "$REPLY"
done
Or, using short-cut notation that some people seems to like:
#!/bin/sh
[ "$#" -gt 0 ] && printf '%sn' "$@"
[ ! -t 0 ] && cat
|
while IFS= read -r; do
printf 'Got "%s"n' "$REPLY"
done
Note that that changes the behaviour if there are arguments that contain newline characters.
â Stéphane Chazelas
Mar 23 at 15:04
@StéphaneChazelas Yes, command line arguments with literal newlines in them will be broken up into multiple items when they arrive at the loop.
â Kusalananda
Mar 23 at 15:07
add a comment |Â
up vote
2
down vote
accepted
Create data for your while read
loop:
#!/bin/sh
if [ "$#" -gt 0 ]; then
# We have command line arguments.
# Output them with newlines in-between.
printf '%sn' "$@"
else
# No command line arguments.
# Just pass stdin on.
cat
fi |
while IFS= read -r; do
printf 'Got "%s"n' "$REPLY"
done
Note that your concat
example can be done with the while read
loop replaced by tr 'n' ','
or similar.
Also, the -t
test says nothing about whether you have command line arguments or not.
Alternatively, to process both command line arguments and standard input (in that order):
#!/bin/sh
if [ "$#" -gt 0 ]; then
# We have command line arguments.
# Output them with newlines in-between.
printf '%sn' "$@"
fi
if [ ! -t 0 ]; then
# Pass stdin on.
cat
fi
|
while IFS= read -r; do
printf 'Got "%s"n' "$REPLY"
done
Or, using short-cut notation that some people seems to like:
#!/bin/sh
[ "$#" -gt 0 ] && printf '%sn' "$@"
[ ! -t 0 ] && cat
|
while IFS= read -r; do
printf 'Got "%s"n' "$REPLY"
done
Note that that changes the behaviour if there are arguments that contain newline characters.
â Stéphane Chazelas
Mar 23 at 15:04
@StéphaneChazelas Yes, command line arguments with literal newlines in them will be broken up into multiple items when they arrive at the loop.
â Kusalananda
Mar 23 at 15:07
add a comment |Â
up vote
2
down vote
accepted
up vote
2
down vote
accepted
Create data for your while read
loop:
#!/bin/sh
if [ "$#" -gt 0 ]; then
# We have command line arguments.
# Output them with newlines in-between.
printf '%sn' "$@"
else
# No command line arguments.
# Just pass stdin on.
cat
fi |
while IFS= read -r; do
printf 'Got "%s"n' "$REPLY"
done
Note that your concat
example can be done with the while read
loop replaced by tr 'n' ','
or similar.
Also, the -t
test says nothing about whether you have command line arguments or not.
Alternatively, to process both command line arguments and standard input (in that order):
#!/bin/sh
if [ "$#" -gt 0 ]; then
# We have command line arguments.
# Output them with newlines in-between.
printf '%sn' "$@"
fi
if [ ! -t 0 ]; then
# Pass stdin on.
cat
fi
|
while IFS= read -r; do
printf 'Got "%s"n' "$REPLY"
done
Or, using short-cut notation that some people seems to like:
#!/bin/sh
[ "$#" -gt 0 ] && printf '%sn' "$@"
[ ! -t 0 ] && cat
|
while IFS= read -r; do
printf 'Got "%s"n' "$REPLY"
done
Create data for your while read
loop:
#!/bin/sh
if [ "$#" -gt 0 ]; then
# We have command line arguments.
# Output them with newlines in-between.
printf '%sn' "$@"
else
# No command line arguments.
# Just pass stdin on.
cat
fi |
while IFS= read -r; do
printf 'Got "%s"n' "$REPLY"
done
Note that your concat
example can be done with the while read
loop replaced by tr 'n' ','
or similar.
Also, the -t
test says nothing about whether you have command line arguments or not.
Alternatively, to process both command line arguments and standard input (in that order):
#!/bin/sh
if [ "$#" -gt 0 ]; then
# We have command line arguments.
# Output them with newlines in-between.
printf '%sn' "$@"
fi
if [ ! -t 0 ]; then
# Pass stdin on.
cat
fi
|
while IFS= read -r; do
printf 'Got "%s"n' "$REPLY"
done
Or, using short-cut notation that some people seems to like:
#!/bin/sh
[ "$#" -gt 0 ] && printf '%sn' "$@"
[ ! -t 0 ] && cat
|
while IFS= read -r; do
printf 'Got "%s"n' "$REPLY"
done
edited Mar 23 at 15:25
answered Mar 23 at 15:01
Kusalananda
102k13201317
102k13201317
Note that that changes the behaviour if there are arguments that contain newline characters.
â Stéphane Chazelas
Mar 23 at 15:04
@StéphaneChazelas Yes, command line arguments with literal newlines in them will be broken up into multiple items when they arrive at the loop.
â Kusalananda
Mar 23 at 15:07
add a comment |Â
Note that that changes the behaviour if there are arguments that contain newline characters.
â Stéphane Chazelas
Mar 23 at 15:04
@StéphaneChazelas Yes, command line arguments with literal newlines in them will be broken up into multiple items when they arrive at the loop.
â Kusalananda
Mar 23 at 15:07
Note that that changes the behaviour if there are arguments that contain newline characters.
â Stéphane Chazelas
Mar 23 at 15:04
Note that that changes the behaviour if there are arguments that contain newline characters.
â Stéphane Chazelas
Mar 23 at 15:04
@StéphaneChazelas Yes, command line arguments with literal newlines in them will be broken up into multiple items when they arrive at the loop.
â Kusalananda
Mar 23 at 15:07
@StéphaneChazelas Yes, command line arguments with literal newlines in them will be broken up into multiple items when they arrive at the loop.
â Kusalananda
Mar 23 at 15:07
add a comment |Â
up vote
1
down vote
With bash
specifically, you could do:
if [ -t 0 ]; then
args=("$@")
else
readarray -t args
fi
for i in "$args[@]"; do
...
done
add a comment |Â
up vote
1
down vote
With bash
specifically, you could do:
if [ -t 0 ]; then
args=("$@")
else
readarray -t args
fi
for i in "$args[@]"; do
...
done
add a comment |Â
up vote
1
down vote
up vote
1
down vote
With bash
specifically, you could do:
if [ -t 0 ]; then
args=("$@")
else
readarray -t args
fi
for i in "$args[@]"; do
...
done
With bash
specifically, you could do:
if [ -t 0 ]; then
args=("$@")
else
readarray -t args
fi
for i in "$args[@]"; do
...
done
answered Mar 23 at 15:06
Stéphane Chazelas
280k53514846
280k53514846
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f433066%2fbash-succinct-way-to-loop-over-lines-from-stdin-or-command-line-arguments%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
1
What are you actually trying to accomplish ? Sounds like a typical XY question...
â don_crissti
Mar 23 at 13:51
What's the problem you're trying to solve? What kind of processing needs to happen in the loop?
â Kusalananda
Mar 23 at 14:15
thanks for the feedback! I write lots of little bash scripts that I like to be able to accepts args from the command line, or from stdin. The particular script i'm writing now is one that will concatenate arguments using a delimiter, so I can write both
cat /tmp/it | concat
andconcat a b c
and it'd join these arguments together in both cases, trimming each arg and putting a comma between items. e.g.a,b,c
.â Brad Parks
Mar 23 at 14:18