Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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
share|improve this question
1  
I suggest reading Bash FAQ 01 - lots of useful info and advice about traps to avoid. –  jw013 Oct 16 '12 at 20:46
    
For the while read part, see Understanding IFS and the questions linked there. –  Gilles Oct 16 '12 at 22:38
    
For using find, see How can I use two bash commands in -exec of find command? or Executing user defined function in a find -exec call (which this question is mostly a duplicate of). –  Gilles Oct 16 '12 at 22:40

2 Answers 2

up vote 7 down vote accepted

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

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

share|improve this answer
1  
@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

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).

share|improve this answer
    
Thanks, very insightful post. –  RanRag Oct 17 '12 at 7:46

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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