Shamelessly stolen from Greg’s BashFAQ:
unset a i
while IFS= read -r -d $'\0' file; do
a[i++]="$file" # or however you want to process each file
done < <(find /tmp -type f -print0)
Note that the redirection construct used here (cmd1 < <(cmd2)
) is similar to, but not quite the same as the more usual pipeline (cmd2 | cmd1
) — if the commands are shell builtins (e.g. while
), the pipeline version executes them in subshells, and any variables they set (e.g. the array a
) are lost when they exit. cmd1 < <(cmd2)
only runs cmd2 in a subshell, so the array lives past its construction. Warning: this form of redirection is only available in bash, not even bash in sh-emulation mode; you must start your script with #!/bin/bash
.
Also, because the file processing step (in this case, just a[i++]="$file"
, but you might want to do something fancier directly in the loop) has its input redirected, it cannot use any commands that might read from stdin. To avoid this limitation, I tend to use:
unset a i
while IFS= read -r -u3 -d $'\0' file; do
a[i++]="$file" # or however you want to process each file
done 3< <(find /tmp -type f -print0)
…which passes the file list via unit 3, rather than stdin.