find
is always recursive¹, but your:
var=$(find ./ -type f)
is a scalar variable assignment, not an array variable assignment. $var
ends up containing one string: the full output of find
including the newline characters²
An array variable assignment in bash, which copied the zsh syntax is with:
var=( 'first element' second-element etc... )
To get each file as output by find -print0
, you'd need to split the output of find
on NUL characters though. In zsh, you'd use the 0
parameter expansion flag for that³:
var=( ${(0)"$(find . -type f -print0)"} )
Bash has no equivalent and in general can't store NULs in its data structures. However, since version 4.4, you can use its readarray
builtin in combination with process substitution:
readarray -td '' var < <(find . -type f -print0)
readarray
stores each record from its input (here a pipe from find
created via process substitution) as separate elements. With -d ''
, the record separator is NUL instead of newline. With -t
, the record delimiter is removed. It's not needed in current versions of bash as bash can't store NULs in its variables anyway, but we're adding it for future-proofing.
To loop over the elements, you'd do:
for file in "${var[@]}"; do
something with "$file"
done
Here, you could also do without the array and loop directly over the output of find
with:
while IFS= read -rd '' -u3 file; do
something with "$file"
done 3< <(find . -type f -print0)
See also Why is looping over find's output bad practice? for how to properly loop over the files found by find
in general.
¹ unless you tell it explicitly not to descend into some directories with -prune
or -xdev
, or with some find
implementation limit the depth with -maxdepth
. It will however not follow symlinks to directories unless you use the -L
option or -follow
predicate4
² except the trailing ones which are stripped by the command subsitution.
³ well, in zsh
, you wouldn't need find
and that non-standard -print0
in the first place, you'd just use its recursive globs and glob qualifiers: var=( **/*(ND.) )
or var=( ***/*(ND.) )
to follow symlinks.
4 Beware however that -L
/-follow
also has an influence on the behaviour -type
. Here -type f
would end up also selecting symlinks to regular files. With the GNU implementation of find
, you can use -xtype f
with -L
to only select regular files and not symlink to regular files like -type f
does without -L
find
is recursive. If you think it isn't, you could show a concrete example, and perhaps someone could tell what's wrong with it. (Dealing with the NUL-separated filenanes is another issue.) – ilkkachu Jan 04 '23 at 17:55find
manage that for you without needing to save the list of files and then loop over them. Tell us the sort of thing you want to achieve and we can help you with a more direct solution – Chris Davies Jan 04 '23 at 20:05