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
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 jutilisefind
, 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.
xargs
pourraient également être utilisés commexargs -I {} sh -c '...' sh {}
, si lon voulait (cela fait il est possible dexécuter des jobs parallèles avec-P
si on le souhaite).