In my file 'foo' there is a first line: 'a b', and the second line: 'c d':

$ cat foo a b c d 

I want to print in terminal in loop these two lines: one after another:

$ for i in $(cat foo); do echo $i; done 

But in the output 'echo' command breaks the order, so instead of having:

a b c d 

I actually have:

a b c d 
3

2 Answers

for i in $(cat foo) does not loop lines but words (or fields) split by your field separator $IFS. It default to \n\t (space, newline, tab).

If you change your field separator to newline only, you can use your command as is (Disclaimer: please read below!):

IFS=$'\n' for i in $(cat foo); do echo $i; done 

You might want to make a backup of IFS to restore it later:

OLD_IFS="$IFS" . . . IFS="$OLD_IFS" 

Output:

a b c d 

However, this is considered bad practice.

  • Bit Better: while IFS= read -r line; do ... done < file
  • Much better: Use a dedicated tool for your task such as grep, sed or awk.

Please read Why is using a shell loop to process text considered bad practice?.

2

You can use while read for this purpose

[/tmp]$ while read line ; do echo $line ; done < foo a b c d 

Adding a separator for your understanding

[/tmp]$ while read line ; do echo $line ; echo "----" ; done < foo a b ---- c d ---- [/tmp]$ 
4