Reputation: 83
I have a bash script using a while loop to get the basename for every file returned from a find command. I have simplified it to one line here:
$ while read myFile; do echo $(basename $myFile) ; done <<< $(find ./*test* -maxdepth 1 -type f -exec ls {} + 2>/dev/null)
testRelease.sh
In the case of there being no results to the find command, I expected the condition of the while statement to be unfulfilled and the "do" section to be ignored. This is not the case:
$ while read myFile; do echo $(basename $myFile) ; done <<< $(find ./*noMatch* -maxdepth 1 -type f -exec ls {} + 2>/dev/null)
basename: missing operand
Try `basename --help' for more information.
It looks as if the while statement adds a blank line which the condition is trying to process:
$ while read myFile; do echo $myFile ; done <<< $(find ./*noMatch* -maxdepth 1 -type f -exec ls {} + 2>/dev/null)
$
This blank line does not appear when running the find command standalone. What is adding this blank line, and why does the while statement process it when no results are found?
Upvotes: 0
Views: 106
Reputation: 22247
Even when there is no output, you feed at least one empty string into the loop. You can try it with a command which is guaranteed to produce no output. I use the null-command :
for this experiment:
while read; do echo read=$REPLY; done <<<$(:)
produces a single output line, saying just
read=
Upvotes: 1
Reputation: 27235
What is adding this blank line
The here string <<<
is adding a trailing blank line. If you don't want it, you can use process substitution instead:
while read var; do ...; done < <(someCommand)
However, in your case you don't need a loop at all. find -exec
can do the job for you much faster and safer:
find ./*test* -maxdepth 1 -type f -exec basename {} \; 2>/dev/null
Upvotes: 3
Reputation: 22022
Please let me simplify your command as:
while read line; do
echo "line read"
done <<< $(find . 1>/dev/null)
The find command outputs nothing then the code above is equivalent to:
while read line; do
echo "line read"
done <<< ""
It still prints "line read". The manpage of bash
says:
A variant of here documents, the format is:
[n]<<<word
[lines snipped]
The result is supplied as a single string, with a newline appended, to the command on its standard input (or file descriptor n if n is specified).
Then the while
loop reads an empty line to execute echo
.
If you modify the code as:
while read line; do
echo "line read"
done < <(find . 1>/dev/null)
it will output nothing.
Upvotes: 1