Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Store grep output in an array

Tags:

arrays

bash

shell

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?

like image 513
Luca Davanzo Avatar asked Jul 22 '14 14:07

Luca Davanzo


People also ask

How can an array store grep results?

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).

How do I redirect the output of a grep command?

If you wish to append the output at the end of the file, use >> rather than > as the redirection operator. What this actually does is to start cat and grep concurrently. cat will read from q1. txt and try to write it to its standard output, which is connected to the standard input of grep .

Is the output of grep a string?

The -n option of the “grep” command is used to print the output of the search string with the line number of the file.


1 Answers

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).


Above answer (written 7 years ago) 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" .) 
like image 72
anubhava Avatar answered Oct 06 '22 15:10

anubhava