Table of Contents

BASH - Files - Read a file - Read from a command instead of a regular file

some_command | while IFS= read -r line; do
  printf '%s\n' "$line"
done

With find

Process the output of find with a block of commands:

find . -type f -print0 | while IFS= read -r -d '' file; do
    mv "$file" "${file// /_}"
done

NOTE: This reads one filename at a time from the find command and renames the file, replacing spaces with underscores.

  • -print0: uses NUL bytes as filename delimiters.
  • -d '': Instructs it to read all text into the file variable until it finds a NUL byte.
    • By default, find and read delimit their input with newlines; however, since filenames can potentially contain newlines themselves, this default behavior will split up those filenames at the newlines and cause the loop body to fail.
    • IFS= : Set to an empty string, because otherwise read would still strip leading and trailing whitespace.
  • |: Pipe the output from the find command into the while loop.
    • This places the loop in a “sub shell”, which means any state changes you make (changing variables, cd, opening and closing files, etc.) will be lost when the loop finishes.
    • To avoid that, use a Process Substitution - which makes the output of the command_list appear as a filename:
          >(command_list)
          <(command_list)
    • Example:
      <(ls -al)

Another approach

while IFS= read -r line; do
  printf '%s\n' "$line"
done < <(some command)