15

How do I pass a list to for in bash?

I tried

echo "some
different
lines
" | for i ; do 
  echo do something with $i; 
done

but that doesn't work. I also tried to find an explanation with man but there is no man for

EDIT:

I know, I could use while instead, but I think I once saw a solution with for where they didn't define the variable but could use it inside the loop

4
  • use a while read and redirect to your loop. Commented Apr 10, 2015 at 11:25
  • possible duplicate of "for i" without "in [sequence]" ending while using getopt Commented Apr 10, 2015 at 11:37
  • Could you clarify your actual question? It has become unclear to me what you're asking. Commented Apr 10, 2015 at 12:02
  • I already added the answer below Commented Apr 10, 2015 at 12:03

5 Answers 5

28

for iterates over a list of words, like this:

for i in word1 word2 word3; do echo "$i"; done

use a while read loop to iterate over lines:

echo "some
different
lines" | while read -r line; do echo "$line"; done

Here is some useful reading on reading lines in bash.

Sign up to request clarification or add additional context in comments.

1 Comment

But i think I once saw a solution with for where they didn't define the variable but could use it inside the loop
19

This might work but I don't recommend it:

echo "some
different
lines
" | for i in $(cat) ; do
    ...
done

$(cat) will expand everything on stdin but if one of the lines of the echo contains spaces, for will think that's two words. So it might eventually break.

If you want to process a list of words in a loop, this is better:

a=($(echo "some
different
lines
"))
for i in "${a[@]}"; do
    ...
done

Explanation: a=(...) declares an array. $(cmd...) expands to the output of the command. It's still vulnerable for white space but if you quote properly, this can be fixed.

"${a[@]}" expands to a correctly quoted list of elements in the array.

Note: for is a built-in command. Use help for (in bash) instead.

4 Comments

Thats great, and it is the shortest, and if you wrote the string yourself in that loop you can just use a="..." and for i in $a; do ... if you know, that there are no "dangerous" signs in it
Actually, you should use a=("word" "a b" "foo") (3 elements) and then for i in "${a[@]}"; do ...; that would iterate three times. You would get 4 iterations.
But if you don't have spaces and special characters in those lines, you can simply use $a as in my example. (My intention is to lazy reformatting and piping stuff on the console to get some things done)
That's not quite correct. Correct is: If you will never, ever, under no circumstances have spaces ... This is like no one will ever need more than 2 digits to save the year, an attitude which cost a lot of money in 1999.
1

This seems to work :

for x in $(echo a b c); do
  echo $x
done

1 Comment

but it is not a pipe, as asked
1

What about this:

echo " a b c " | for i in $(xargs) ; do echo "$i"; done

Result:

a
b
c

Comments

0

This is not a pipe, but quite similar:

args="some
different
lines";
set -- $args; 
for i ; do 
  echo $i;
done

cause for defaults to $@ if no in seq is given.

maybe you can shorten this a bit somehow?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.