Supposons que je veuille trouver tous les fichiers .txt et rechercher une chaîne. Je ferais:

find ./ -type f -name "*.txt" -exec egrep -iH "something" "{}" \; 

Et si je veux faire un filtrage plus complexe, comme ceci:

egrep something file.txt | egrep somethingelse | egrep other 

À lintérieur de find -exec? (ou similaire)

Veuillez garder à lesprit que je recherche une solution que je pourrais facilement taper quand jen ai besoin. Je sais que cela pourrait être fait avec quelques lignes en utilisant un script shell, mais ce nest pas ce que je recherche.

Réponse

Si vous devez le faire depuis find, vous devez appeler un shell:

find ./ -type f -name "*.txt" -exec sh -c "grep -EiH something "$1" | grep -E somethingelse | grep -E other" sh {} \; 

Dautres alternatives incluent lutilisation de xargs à la place:

find ./ -type f -name "*.txt" | xargs -I{} grep -EiH something {} | grep -EiH somethingelse | grep -EiH other 

Ou , beaucoup plus sûr pour les noms de fichiers arbitraires (en supposant que votre find prend en charge -print0):

find ./ -type f -name "*.txt" -print0 | xargs -0 grep -EiH something {} | grep -Ei somethingelse | grep -Ei other 

Ou, vous pouvez simplement utiliser une boucle shell à la place:

find ./ -type f -name "*.txt" -print0 | while IFS= read -d "" file; do grep -Ei something "$file" | grep -Ei somethingelse | grep -Ei other done 

Commentaires

  • Le premier est exactement ce que je cherchais. Extrêmement simple et assez petit pour taper en fonction de mes besoins. Merci.
  • … et xargs pourraient également être utilisés comme xargs -I {} sh -c '...' sh {}, si lon voulait (cela fait il est possible dexécuter des jobs parallèles avec -P si on le souhaite).

Réponse

Modifier: Cette réponse nest pas préférée , mais elle est laissée ici pour comparaison et illustration des pièges potentiellement dangereux dans les scripts bash.


Vous pouvez mettre bash (ou un autre shell) comme commande -exec:

 find -type -f -name "*.txt" -exec bash -c "egrep -iH something "{}" | egrep somethingelse | egrep other" \;  

Lun des inconvénients de le faire de cette façon est que cela crée plus potentiel de problèmes de citations imbriquées lorsque vos commandes deviennent plus complexes. Si vous voulez éviter cela, vous pouvez le décomposer en une boucle for:

 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  

Commentaires

  • Le premier est exactement ce que je cherchais. Extrêmement simple et assez petit pour taper en fonction de mes besoins. Merci.
  • Cette boucle for est une très mauvaise idée. Également connue sous le nom de bash pitfall # 1 .
  • Ce "{}" dans votre première commande peut même conduire à une injection de code. Imaginez que vous ayez des fichiers de ma part et que ' s un fichier nommé littéralement " & rm -rf ~ & : ".txt. Heureusement pour vous -type -f nest pas valide, il vient de sauvegarder votre répertoire personnel. Corrigez la faute de frappe et réessayez. 🙂 terdon la bien fait: find … -exec sh -c '… "$1" …' foo {} \;.
  • Merci pour linformation! Oui, le -type -f est une faute de frappe que je fais constamment lorsque jutilise find, et je nai pas ' t le remarquer dans ma réponse. Oups. La réponse de terdon ' est meilleure, mais je ' vais laisser cela à des fins de comparaison.
  • @terdon: tx pour référencer la page mywiki.wooledge.org. Cest ' que cest bien davoir un tas de médecins généralistes bien résumés en un seul endroit.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *