46

I am trying to read the output of a command in bash using a while loop.

while read -r line
do
    echo "$line"
done <<< $(find . -type f)

The output I got

ranveer@ranveer:~/tmp$ bash test.sh
./test.py ./test1.py ./out1 ./test.sh ./out ./out2 ./hello
ranveer@ranveer:~/tmp$ 

After this I tried

$(find . -type f) | 
while read -r line
do
    echo "$line"
done 

but it generated an error test.sh: line 5: ./test.py: Permission denied.

So, how do I read it line by line because I think currently it is slurping the entire line at once.

Required output:

./test.py
./test1.py
./out1
./test.sh
./out
./out2
./hello
48

There's a mistake, you need < <(command) not <<<$(command)

< <( ) is a Process Substitution, $() is a command substitution and <<< is a here-string.

  • 2
    @RanRag Stop trying to put $( ) around everything! That's the syntax for command substitution, which is only one way to use command output. Pipes and process substitution and here-strings are others, and they all have different syntax, naturally. You shouldn't be parsing file names anyways unless you really know what you are doing. – jw013 Oct 16 '12 at 20:41
  • Thanks it worked will read more about Process Substitution. – RanRag Oct 16 '12 at 20:44
  • @jw013: I am a bash beginner. In future will keep your suggestion in my mind. – RanRag Oct 16 '12 at 20:45
13

Note that there's nothing stopping file names from containing newline characters. The canonical way to run a command for each file found by find is.

find . -type f -exec cmd {} \;

And if you want things done in bash:

find . -type f -exec bash -c '
  for file do
    something with "$file"
  done' bash {} +

Also, the canonical way to call the "read" command in scripts (if you don't want it to do extra processing on the input) is:

IFS= read -r var

-r is to stop read from treating backslash characters specially (as an escape character for separators and newline), And IFS= to set the list of separators to the empty string for read (otherwise if any whitespace character was in that list, they would be stripped from the beginning and end of the input).

Using loops in shells is usually a bad idea (not how things are done in shells where you make several tools work collectively and concurrently to a task rather than running one or more tools hundreds of times in sequence).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.