Suponhamos que eu queira encontrar todos os .txt
arquivos e pesquisar alguma string. Eu faria:
find ./ -type f -name "*.txt" -exec egrep -iH "something" "{}" \;
E se eu quiser fazer uma filtragem mais complexa, como esta:
egrep something file.txt | egrep somethingelse | egrep other
Por dentro de find -exec? (ou semelhante)
Lembre-se de que estou procurando uma solução que possa digitar facilmente quando precisar. Eu sei que isso poderia ser feito com algumas linhas usando um script de shell, mas não é isso que estou procurando.
Resposta
Se você deve fazer isso de dentro de find, você precisa chamar um shell:
find ./ -type f -name "*.txt" -exec sh -c "grep -EiH something "$1" | grep -E somethingelse | grep -E other" sh {} \;
Outras alternativas incluem o uso de xargs
em vez:
find ./ -type f -name "*.txt" | xargs -I{} grep -EiH something {} | grep -EiH somethingelse | grep -EiH other
Ou , muito mais seguro para nomes de arquivo arbitrários (assumindo que seu find
suporte -print0
):
find ./ -type f -name "*.txt" -print0 | xargs -0 grep -EiH something {} | grep -Ei somethingelse | grep -Ei other
Ou, em vez disso, você pode usar apenas um loop de shell:
find ./ -type f -name "*.txt" -print0 | while IFS= read -d "" file; do grep -Ei something "$file" | grep -Ei somethingelse | grep -Ei other done
Comentários
Resposta
Editar: esta resposta é não preferida , mas é deixada aqui para comparação e ilustração de armadilhas potencialmente perigosas no script bash.
Você pode colocar bash
(ou outro shell) como seu comando -exec
:
find -type -f -name "*.txt" -exec bash -c "egrep -iH something "{}" | egrep somethingelse | egrep other" \;
Uma das desvantagens de fazer dessa forma é que cria mais potencial para problemas de cotação aninhados conforme seus comandos se tornam mais complexos. Se quiser evitar isso, você pode dividi-lo em um for
-loop:
for i in $(find -type -f -name "*.txt"); do if egrep -iH something "$i" | egrep somethingelse | egrep other; then echo "Found something: $i" fi done
Comentários
- O primeiro é exatamente o que eu estava procurando. Extremamente simples e pequeno o suficiente para digitar dependendo das minhas necessidades. Obrigado.
- Esse
for
loop é uma ideia muito ruim. Também conhecido como bash pitfall # 1 . - Este
"{}"
em seu primeiro comando pode até levar à injeção de código. Imagine que você tenha obtido arquivos comigo e ' um arquivo chamado literalmente" & rm -rf ~ & : ".txt
. Felizmente para você-type -f
é inválido, acabou de salvar seu diretório pessoal. Corrija o erro de digitação e tente novamente. 🙂 terdon fez certo:find … -exec sh -c '… "$1" …' foo {} \;
. - Obrigado pela informação! Sim, o
-type -f
é um erro de digitação que cometi constantemente ao usarfind
e não ' não percebo na minha resposta. Opa. terdon ' a resposta é melhor, mas ' deixarei isso para fins comparativos. - @terdon: tx para consultar a página mywiki.wooledge.org. É ' bom ter um monte de GPs perfeitamente resumidos em um só lugar.
xargs
também poderiam ser usados comoxargs -I {} sh -c '...' sh {}
, se alguém quisesse (faz é possível executar trabalhos paralelos com-P
se alguém quiser).