Comment exécuter find -exec?

477

Je voudrais trouver les fichiers dans le répertoire actuel qui contiennent le texte "chrome".

$ find . -exec grep chrome
find: missing argument to `-exec'

Qu'est-ce que je fais mal?

ripper234
la source
Je suisfind: Only one instance of {} is supported with -exec ... +
Costa
2
Connexes: comment utiliser -execavecfind
Kusalananda

Réponses:

710

Vous avez manqué un ;(échappé ici \;pour empêcher le shell de l'interpréter) ou un +et a {}:

find . -exec grep chrome {} \;

ou

find . -exec grep chrome {} +

finds'exécutera grepet remplacera {}par le nom de fichier trouvé. La différence entre ;et +est qu’une ;seule grepcommande est exécutée pour chaque fichier alors qu’avec +autant de fichiers que possible, les paramètres sont indiqués en même greptemps.

bmk
la source
30
Si vous utilisez le \; La construction de fin, grep, est transmise un fichier à la fois. Par conséquent, elle n’affiche pas le nom du fichier par défaut, mais uniquement les lignes correspondantes. Pour obtenir une liste de fichiers, ajoutez plutôt use grep -lsdans la construction find.
Caleb
9
find . -exec grep foo {} +vous montrera une sortie comme celle-ci./dir/file.py:from foo import bar
sg
10
find . -exec grep foo {} \;va vous montrer la sortie comme çafrom foo import bar
sg
9
find . -exec grep -l foo {} +va vous montrer la sortie comme ça./dir/file.py
sg
8
find . -exec grep -l foo {} \;va vous montrer la sortie comme ça./dir/file.py
sg
46

Vous n'avez pas besoin d'utiliser findpour cela du tout; grep est capable de gérer l’ouverture des fichiers à partir d’une liste globale de tout ce qui se trouve dans le répertoire courant:

grep chrome *

... ou même récursivement pour le dossier et tout ce qu'il contient:

grep chrome . -R
Caleb
la source
22
grep s'étouffera si l'extension passe par ARG_MAX. -R visitera tout en utilisant find on pourra plus facilement ajouter des primitives pour exclure certains fichiers (-name, etc.) ou même ne pas visiter les sous-arbres (-prune).
Mel
6
Bons points @Mel. Mon argument était que, selon toute vraisemblance, la partie demanderesse rendait les choses plus complexes qu’elles n’auraient dû être en indiquant findquand on greppourrait faire le travail, mais dans certains cas, il serait plus efficace d’utiliser find pour affiner la liste des dossiers avant de sortir. à grep.
Caleb
4
@Mel grepne s'étouffe pas dans un tel cas, le execfait.
Chris Down
Ne fonctionne que si tous les fichiers se trouvent dans le même répertoire, pas lorsqu'ils sont répartis sur des sous-répertoires.
Yaba
1
@Yaba Ma réponse indique comment gérer le cas de fichiers répartis sur des sous-répertoires.
Caleb
18
find . | xargs grep 'chrome'

vous pouvez aussi faire:

find . | xargs grep 'chrome' -ls

Le premier vous montre les lignes dans les fichiers, le second ne fait que lister les fichiers.

L'option de Caleb est plus nette, moins de frappes.

Mathew
la source
11
Le problème, xargsc'est qu'il s'attend à ce que son entrée soit citée d'une manière particulière qui findne produit pas. Donc, find … | xargs …ne fonctionne pas si vous avez des noms de fichiers contenant des espaces ou \'".
Gilles
3
@ Gilles Vous pouvez contourner ce problème en utilisant quelque chose comme find . | xargs -n1 -iX grep "X" 'chrome'pour que les arguments soient alimentés un par un et cités. De toute évidence, c’est un moyen terriblement inefficace de traiter cet exemple, mais dans certaines situations, c’est agréable.
Caleb
Pour être complet, nous devrions également mentionner l'option -i pour l'insensibilité à la casse avec 'grep'. De plus, il y a -iname en recherche pour insensibilité à la casse.
Mathew
9
@Caleb: Le seul moyen fiable de xargsgérer les noms de fichiers Linux est d' find ... -print0 | xargs -0utiliser NUL comme séparateur. Alternative - xargs -d '\n'utilisation de newline comme séparateur, fiabilité à 99%.
Grawity
J'utilise cela souvent, mais cela échouera pour de très longues listes de noms de fichiers, à ce moment-là, trouver -exec devient le gagnant.
Spacemoose
5

Trouver est un moyen et vous pouvez essayer the_silver_searcheralors tout ce que vous devez faire est

ag chrome

Il va chercher chrome dans tous les fichiers (inclure les sous-répertoires) et il est plus rapide que trouver

Demander et apprendre
la source
Il existe également un pt (chercheur de platine, disponible sur github.com/monochromegane/the_platinum_searcher ) qui, à mon humble avis , fait le travail plus rapidement - n’a peut-être pas d'importance s'il n'y a que quelques fichiers.
Hopping Bunny
1

Pour voir la liste des fichiers au lieu des lignes:

grep -l "chrome" *

ou:

grep -r -l "chrome" .
mateusz.szymborski
la source
1

Voici un exemple de la façon dont j'utilise habituellement find / exec ...

find  . -name "*.py" -print -exec fgrep hello {} \;

Ceci recherche récursivement tous les fichiers .py et, pour chaque fichier, imprime le nom du fichier et fgrep pour 'hello' sur ce fichier (pour chaque). La sortie ressemble à (en ai juste lancé une aujourd'hui):

./r1.py
./cgi-bin/tst1.py
print "hello"
./app/__init__.py
./app/views.py
./app/flask1.py
./run.py
./tst2.py
print "hello again"
jon
la source
1
ne gâchez pas votre flux de travail, mais vous pourriez aimer: find . -name "*.py" -exec fgrep -l hello {} \; - il imprimera les noms de fichier des fichiers correspondants, et rien d'autre
Jeff Schaller