1

I want to save all filenames that matches the pattern in bash array.

My solution does not work. I think the problem is because of pipe usage, but I don't know how to fix it.

i=0
find . -type f | grep -oP "some pattern" | while read -r line; do
    arr[$i]=$line;
    let i=i+1;
done
4

With bash-4.4 and above, you'd use:

readarray -d '' -t arr < <(
  find . -type f -print0 | grep -zP 'some pattern')

With older bash versions:

arr=()
while IFS= read -rd '' file; do
  arr+=("$file")
done < <(find . -type f -print0 | grep -zP 'some pattern')

Or (to be compatible to even older versions of bash that didn't have the zsh-style arr+=() syntax):

arr=() i=0
while IFS= read -rd '' file; do
  arr[i++]=$line
done < <(find . -type f | grep -zP 'some pattern')

Your approach has several problems:

  • with -o, grep only prints the parts of the records that match the pattern as opposed to the full record. You don't want it here.
  • find's default newline-delimited output can't be post processed as the newline character is as valid as any in a file path. You need a NUL-delimited output (so -print0 in find and -z in grep to process NUL-delimited records.
  • you also forgot to pass IFS= to read.
  • in bash, and without the lastpipe option, the last part of a pipe line runs in a subshell, so there, you'd only be updating the $arr of that subshell.

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.