while read -d $'\0' file; do found=yes echo "Modifying $file" chmod 755 "$file" done < <(find /data -type f -perm 400 -print0) if [ "x$found" != "xyes" ]; then echo "No files found to modify" fi
This uses the process replace function in Bash . It is equivalent
find ... | while read ...
except that while read is executed in a subshell, so we cannot set the variables that will be visible in the outer shell. Instead, we can use process substitution. <(cmd) starts cmd in a subshell, and its standard output is redirected to the named pipe. The name of this pipe is replaced with an external command.
Then we use < to redirect from this channel to the standard input of the while read command, which in turn reads each delimited record and stores the value in the specified name ( file in this case). By default, read split into newlines. For most files this will be fine; You can do:
while read file; do ... done < <(find /data -type f -perm 400)
and all will be well. But it is technically possible to have a new line in the file name, in which case it will break. The -print0 argument to search and the -d $'\0' read argument forces them to use an empty character as a delimiter, which is not valid in the file name.
source share