Você precisa citar "$cmd" - e talvez evite as aspas duplas " . De qualquer forma, para executar isso você precisa eval - e isso é devido ao |pipe . Uma variável de shell não se expande além dos limites de um único comando simples - e você está tentando executar um comando composto.
Então:
cmd='grep -i "word1" filename | grep -i "word2"'
eval "$cmd"
Provavelmente, quando você estava expandindo $cmd sem aspas, correu para geração de nome de arquivo e / ou $IFS problemas. Apenas certifique-se de que é citado de forma confiável e você ficará bem. Também verifique se o que está em "word[12]" não contém aspas duplas ou barras invertidas ou qualquer outra coisa - senão você precisará reavaliar seu estilo de citação lá.
Olhando mais de perto para o seu erro e posso dizer exatamente o que foi:
grep: |: No such file or directory
grep: grep: No such file or directory
Então, se eu fizer isso:
echo | echo
A primeira echo imprime uma \n ewline para a segunda echo ' stdin . Se eu fizer:
set \| echo
echo "$@"
O primeiro echo imprime cada um dos seus argumentos, que são | pipe e echo , respectivamente.
A diferença é que o | pipe no primeiro caso é interpretado pelo analisador do shell como um token e é interpretado como tal. No segundo caso, ao mesmo tempo em que o shell está verificando o token de | do canal, ele também está verificando o token $ expand - e assim o | pipe ainda não está lá porque "$@" tem ainda não foi substituído pelo seu valor.
Então, se você fizer isso:
grep -i "word" filename \| grep -i "word2"
... é provável que você obtenha os mesmos resultados porque o | não delimita os comandos e, em vez disso, é um argumento para grep em sua posição infiles .
Veja aqui quantos campos você recebe quando divide $cmd com o valor padrão $IFS :
printf '<%s> ' $cmd
<grep> <-i> <"word1"> <filename> <|> <grep> <-i> <"word2">
E aqui está o que a geração de nome de arquivo pode fazer:
touch 'echo 1simple &&' 'echo 2simple'
eval echo*