I'm trying to search for files using find, and put those files into a Bash array so that I can do other operations on them (e.g. ls or grep them). But I can't figure out why readarray isn't reading the find output as it's piped into it.

Say I have two files in the current directory, file1.txt and file2.txt. So the find output is as follows:

$ find . -name "file*"

So I want to pipe that into an array whose two elements are the strings "./file1.txt" and "./file2.txt" (without quotes, obviously).

I've tried this, among a few other things:

$ declare -a FILES
$ find . -name "file*" | readarray FILES
$ echo "${FILES[@]}"; echo "${#FILES[@]}"


As you can see from the echo output, my array is empty.

So what exactly am I doing wrong here? Why is readarray not reading find's output as its standard input and putting those strings into the array?


When using a pipeline, bash runs the commands in subshells. Therefore, the array is populated, but in a subshell, so the parent shell has no access to it.

Use process substitution:

readarray FILES < <(find)

Note that it doesn't work for files with newlines in their names. If that could be the case, you need a more elaborate syntax:

readarray -d '' < <(find -print0)
  • 3
    In order to support newlines, this is sufficient: readarray -d '' < <(find your_args -print0) – VasyaNovikov Jan 18 '18 at 13:40

The correct solution is:

unset a; declare -a a
while IFS= read -r -u3 -d $'\0' file; do
    a+=( "$file" )        # or however you want to process each file
done 3< <(find /tmp -type f -print0)

That's similar to what Greg's BashFAQ 020 explains in detail and this answer covers.

Has no problem with odd named files (that contain no NUL in the name), with spaces or new lines. And the result is set in an array, which makes it useful for further processing.

  • Great, this is a better solution to the problem I was trying to solve in the first place. +1 as soon as my rep reaches 15 :) – villapx Feb 17 '16 at 19:12

readarray can also read from stdin

readarray FILES <<< "$(find . -name "file*")"; echo "${#FILES[@]}"
  • This doesn't work with find -print0 for protecting against "unexpected" file names. – roaima Mar 11 '19 at 14:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.