How to pass files found by find as arguments?
Use arrays.
If you don't need to handle the possibility of newlines in your filenames, then you could get away with
mapfile -t ABC_FILES < <(find -L some/dir -name \*.abc | sort)
mapfile -t XYZ_FILES < <(find -L other/dir -name \*.xyz | sort)
then
./program --abc-files "${ABC_FILES[@]}" --xyz-files "${XYZ_FILES[@]}"
If you do need to handle newlines within filenames, and have bash >= 4.4, you can use -print0
and -d ''
to null-terminate the names during array construction:
mapfile -td '' ABC_FILES < <(find -L some/dir -name \*.abc -print0 | sort -z)
(and similarly for the XYZ_FILES
). If you don't have the newer bash, then you could use a null-terminated read loop to append filenames to the arrays e.g.
ABC_FILES=()
while IFS= read -rd '' f; do ABC_FILES+=( "$f" ); done < <(find -L some/dir -name \*.abc -print0 | sort -z)
You can use IFS=newline (assuming no filenames contain newline) but you must set it in the outer shell BEFORE the substitution:
$ ls -1
a file with spaces
able
alpha
baker
boo hoo hoo
bravo
$ # note semicolon here; it's not enough to be in the environment passed
$ # to printf, it must be in the environment OF THE SHELL WHILE PARSING
$ IFS=$'\n'; printf '%s\n' --afiles $(find . -name 'a*') --bfiles $(find . -name 'b*')
--afiles
./able
./a file with spaces
./alpha
--bfiles
./bravo
./boo hoo hoo
./baker
With zsh
but not bash
you can use null $'\0'
as well. Even in bash
you could handle newline if there's one sufficiently strange character that is never used like
IFS=$'\1'; ... $(find ... -print0 | tr '\0' '\1') ...
However, this approach does not handle the additional request you made in comments on @steeldriver's answer to omit the --afiles if find a is empty.