You need to quote
"$cmd" - and maybe avoid the
"double-quotes. Anyway, to run this you do need to
eval it - and this is due to the
|pipe. A shell variable does not expand beyond the limits of a single simple command - and you're trying to run a compound command.
cmd='grep -i "word1" filename | grep -i "word2"'
Probably when you were expanding
$cmd without quotes you ran into filename generation and/or
$IFS issues. Just make sure it's reliably quoted and you'll be fine. Also verify that whatever is in
"word" doesn't contain double-quotes or backslashes or whatever - else you'll need to reevaluate your quoting style there.
Looking closer now at your error and I can tell you exactly what it was:
grep: |: No such file or directory
grep: grep: No such file or directory
So if I do:
echo | echo
echo prints a
\newline to the second
stdin. If I do:
set \| echo
echo prints each of its arguments, which are
The difference is that the
|pipe in the first case is interpreted by the shell's parser to be a token and is interpreted as such. In the second case, at the same the shell is scanning for the
|pipe token it is also scanning for the
$expand token - and so the
|pipe is not yet there to be found because
"$@" has not yet been replaced with its value.
So if you do:
grep -i "word" filename \| grep -i "word2"
...you're likely to get the same results because the
| there does not delimit the commands, and is instead an argument to
grep in its infiles position.
Here's a look at how many fields you get when you split
$cmd with a default
printf '<%s> ' $cmd
<grep> <-i> <"word1"> <filename> <|> <grep> <-i> <"word2">
And here's what filename generation might do:
touch 'echo 1simple &&' 'echo 2simple'