Question

I am struggling with passing several grep patterns that are contained within a variable. This is the code I have:

#!/bin/bash
GREP="$(which grep)"
GREP_MY_OPTIONS="-c"
for i in {-2..2}
do
  GREP_MY_OPTIONS+=" -e "$(date --date="$i day" +'%Y-%m-%d')
done
echo $GREP_MY_OPTIONS

IFS=$'\n'
MYARRAY=( $(${GREP} ${GREP_MY_OPTIONS} "/home/user/this path has spaces in it/"*"/abc.xyz" | ${GREP} -v :0$ ) )

This is what I wanted it to do:

  • determine/define where grep is
  • assign a variable (GREP_MY_OPTIONS) holding parameters I will pass to grep
  • assign several patterns to GREP_MY_OPTIONS
  • using grep and the patterns I have stored in $GREP_MY_OPTIONS search several files within a path that contains spaces and hold them in an array

When I use "echo $GREP_MY_OPTIONS" it is generating what I expected but when I run the script it fails with an error of:

/bin/grep: invalid option -- ' '

What am I doing wrong? If the path does not have spaces in it everything seems to work fine so I think it is something to do with the IFS but I'm not sure.

Was it helpful?

Solution 2

If you build the GREP_MY_OPTIONS as an array instead of as a simple string, you can get the original outline script to work sensibly:

#!/bin/bash
path="/home/user/this path has spaces in it"
GREP="$(which grep)"
GREP_MY_OPTIONS=("-c")
j=1
for i in {-2..2}
do
    GREP_MY_OPTIONS[$((j++))]="-e"
    GREP_MY_OPTIONS[$((j++))]=$(date --date="$i day" +'%Y-%m-%d')
done

IFS=$'\n'
MYARRAY=( $(${GREP} "${GREP_MY_OPTIONS[@]}" "$path/"*"/abc.xyz" | ${GREP} -v :0$ ) )

I'm not clear why you use GREP="$(which grep)" since you will execute the same grep as if you wrote grep directly — unless, I suppose, you have some alias for grep (which is then the problem; don't alias grep).

OTHER TIPS

If you want to grep some content in a set of paths, you can do the following:

find <directory> -type f -print0 |
    grep "/home/user/this path has spaces in it/\"*\"/abc.xyz" |
    xargs -I {} grep <your_options> -f <patterns> {}

So that <patterns> is a file containing the patterns you want to search for in each file from directory.

Considering your answer, this shall do what you want:

find "/path\ with\ spaces/" -type f | xargs -I {} grep -H -c -e 2013-01-17 {}

From man grep:

   -H, --with-filename
          Print  the  file  name for each match.  This is the default when
          there is more than one file to search.

Since you want to insert the elements into an array, you can do the following:

IFS=$'\n'; array=( $(find "/path\ with\ spaces/" -type f -print0 |
    xargs -I {} grep -H -c -e 2013-01-17 "{}") )

And then use the values as:

echo ${array[0]}
echo ${array[1]}
echo ${array[...]}

When using variables to pass the parameters, use eval to evaluate the entire line. Do the following:

parameters="-H -c"
eval "grep ${parameters} file"

You can do one thing without making things complex:

First do a change directory in your script like following:

cd /home/user/this\ path\ has\ spaces\ in\ it/
$ pwd
/home/user/this path has spaces in it

or

$ cd "/home/user/this path has spaces in it/"
$ pwd
/home/user/this path has spaces in it

Then do what ever your want in your script.

$(${GREP} ${GREP_MY_OPTIONS} */abc.xyz)

EDIT :

[sgeorge@sgeorge-ld stack1]$ ls -l
total 4
drwxr-xr-x 2 sgeorge eng 4096 Jan 19 06:05 test tesd
[sgeorge@sgeorge-ld stack1]$ cat test\ tesd/file 
SUKU
[sgeorge@sgeorge-ld stack1]$ grep SUKU */file
SUKU

EDIT :

[sgeorge@sgeorge-ld stack1]$ find */* -print | xargs -I {} grep SUKU {}
SUKU
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top