1

I have 2 bash functions catall and grepall

catall works fine, catting every file it finds with the file name printed first, then the content and a new line

catall ()
{
  find . -name $1 | xargs -I % sh -c 'echo %; cat %; echo"" '
}


grepall ()
{
  find . -name $1 | xargs -I % sh -c 'echo %; cat % | grep $2; echo"" '
}

But grepall doesn't work, is should do the same as catall but with a grep stage on the content of the file

Why is $2 not sub'ed

Can you make this grepall work ?

Bernhard
  • 3,619
  • 1
  • 25
  • 50
dmc
  • 401
  • 4
  • 14

1 Answers1

2

It is because you are forking a new shell process using sh -c and all the variable of parent shell are not available in child shell unless you export them.

Use this function to make it work:

grepall () {
   export p="$2"; find . -name $1 | xargs -I % sh -c 'echo %; grep "$p" %; echo "" ';
}

It works now because we are creating an exported variable p which becomes available in sub shell also.

Since you are forking a new shell anyway you don't really need to call xargsa as find can do the job for you:

grepall () {
   export p="$2"; find . -name $1 -exec sh -c 'echo $1; grep "$p" $1; echo "" ' - {} \;;
}
anubhava
  • 761,203
  • 64
  • 569
  • 643
  • nice one, just in time to look at my boring test results – dmc Aug 28 '14 at 09:46
  • You'll probably want to `unset p` so you don't pollute the environment of the rest of the script. Or, make the env assignment temporary with `find . -name "$1" | p="$2" xargs -I % sh -c 'echo %; grep "$p" %; echo "" '` -- don't forget to quote `"$1"` – glenn jackman Aug 28 '14 at 10:52
  • 1
    last thought: keep using `$2` in the sh script, but pass the function's parameters to the shell: `grepall () { find . -name "$1" | xargs -I % sh -c 'echo %; grep "$2" %; echo' _ "$@"; }` – glenn jackman Aug 28 '14 at 10:59