79

I need to search a pattern in a directory and save the names of the files which contain it in an array.

Searching for pattern:

grep -HR "pattern" . | cut -d: -f1

This prints me all filenames that contain "pattern".

If I try:

targets=$(grep  -HR "pattern" . | cut -d: -f1)
length=${#targets[@]}
for ((i = 0; i != length; i++)); do
   echo "target $i: '${targets[i]}'"
done

This prints only one element that contains a string with all filnames.

output: target 0: 'file0 file1 .. fileN'

But I need:

 output: target 0: 'file0'
 output: target 1: 'file1'
 .....
 output: target N: 'fileN'

How can I achieve the result without doing a boring split operation on targets?

1
  • Other answer is a generic way to build an array by running any command and this question is specific to grep --null -HR to produce output with NUL bytes. Commented Nov 30, 2021 at 8:08

1 Answer 1

119

Old answer (written in the year 2014) made an assumption that output filenames won't contain special characters like whitespaces or globs. Here is a safe way to read those special filenames into an array: (will work with older bash versions)

while IFS= read -rd ''; do
   targets+=("$REPLY")
done < <(grep --null -HRl "pattern" .)

# check content of array
declare -p targets

On BASH 4+ you can use readarray instead of a loop:

readarray -d '' -t targets < <(grep --null -HRl "pattern" .)

Old Answer:

You can use:

targets=($(grep -HRl "pattern" .))

Note use of (...) for array creation in BASH.

Also you can use grep -l to get only file names in grep's output (as shown in my command).

Sign up to request clarification or add additional context in comments.

7 Comments

spectacular! I was already taking a look at "-l" option, btw great hit. Can you explain why works adding two brackets?
That is syntax of array creation in BASH. If you remove outer (..) then you are merely assigning outout of grep to a simple shell variable which won't be treated as array.
If that is the possibility then use grep --null with IFS= to create array
Does this work with Posix-ly OS'es, like some of the BSDs and Solaris? I don't see -H or -R.
$REPLY is internally set by bash if no variable name is provided.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.