Usually when working with filenames we need to terminate each result record uniquely using the special null-character. That’s because filenames may contain special symbols, including white-space and even the newline character “\n”.
There is already a great answer how to do this in the StackOverflow topic “Capturing output of find . -print0 into a bash array”. The proposed solution doesn’t invoke any sub-shells, which is great, and also explains all caveats in detail. In order to become really universal, this solution must not rely on the static file-descriptor “3”. Another great answer at SO gives an example on how to dynamically use the next available file-descriptor.
Here is the solution which works without using sub-shells and without depending on a static FD:
a=() while IFS='' read -r -u"$FD" -d $'\0' file; do # note that $IFS is having the default value here a+=("$file") # or however you want to process each file done {FD}< <(find /tmp -type f -print0) exec {FD}<&- # close the file descriptor # the result is available outside the loop, too echo "${a[0]}" # 1st file echo "${a[1]}" # 2nd file
October 23, 2021 at 12:57 am
This is very clever; I had no idea bash could do this. Thank you for sharing it!
After reading the REDIRECTION section of the bash man page, I think this example could be slightly improved by freeing up the file descriptor with something like`exec {FD}>&-` after the loop is finished.
October 24, 2021 at 10:53 pm
Nice catch, C! 🙂 A file descriptor is leaked, indeed. I’ve updated the example.