Utiliser un point-virgule (;) vs plus (+) avec exec dans find

Pourquoi y a-t-il une différence de sortie entre l’utilisation de

find . -exec ls '{}' \+ 

et

 find . -exec ls '{}' \; 

J’ai eu:

 $ find . -exec ls \{\} \+ ./file1 ./file2 .: file1 file2 testdir1 ./testdir1: testdir2 ./testdir1/testdir2: $ find . -exec ls \{\} \; file1 file2 testdir1 testdir2 ./file2 ./file1 

Cela pourrait être mieux illustré avec un exemple. Disons que find ces fichiers:

 file1 file2 file3 

Utiliser -exec avec un point-virgule ( find . -exec ls '{}' \; ) s’exécutera

 ls file1 ls file2 ls file3 

Mais si vous utilisez plutôt un signe plus ( find . -exec ls '{}' \+ ), autant de noms de fichiers que possible sont passés en arguments à une seule commande:

 ls file1 file2 file3 

Le nombre de noms de fichiers n’est limité que par la longueur maximale de la ligne de commande du système. Si la commande dépasse cette longueur, la commande sera appelée plusieurs fois.

Toutes les réponses à ce jour sont correctes. Je propose ceci comme une démonstration plus claire du comportement décrit en utilisant echo plutôt que ls :

Avec un point-virgule, la commande echo est appelée une fois par fichier (ou autre object du système de fichiers) trouvé:

 $ find . -name 'test*' -exec echo {} \; ./test.c ./test.cpp ./test.new ./test.php ./test.py ./test.sh 

Avec un plus, la commande echo est appelée une seule fois. Chaque fichier trouvé est passé en argument.

 $ find . -name 'test*' -exec echo {} \+ ./test.c ./test.cpp ./test.new ./test.php ./test.py ./test.sh 

Si find génère un grand nombre de résultats, vous pouvez constater que la commande appelée appelle un nombre limité d’arguments.

de l’homme

-exec commande;

Exécuter la commande; true si 0 est renvoyé. Tous les arguments suivants à trouver sont considérés comme des arguments pour la commande jusqu’à ce qu’un argument consistant en ‘;’ est rencontré. La chaîne ‘{}’ est remplacée par le nom du fichier en cours de traitement partout où elle apparaît dans les arguments de la commande, pas seulement dans les arguments où elle est seule, comme dans certaines versions de find. Il faudra peut-être échapper ces deux constructions (avec un «\») ou les citer pour les protéger de l’extension par le shell. Voir la section EXEMPLES pour des exemples d’utilisation de l’option ‘-exec’. La commande spécifiée est exécutée une fois pour chaque fichier correspondant. La commande est exécutée dans le répertoire de départ. Il y a des problèmes de sécurité inévitables concernant l’utilisation de l’option -exec; vous devriez utiliser l’option -execdir à la place.

Commande -exec {} +

Cette variante de l’option -exec exécute la commande spécifiée sur les fichiers sélectionnés, mais la ligne de commande est créée en ajoutant chaque nom de fichier sélectionné à la fin. le nombre total d’appels de la commande sera beaucoup moins important que le nombre de fichiers correspondants. La ligne de commande est construite de la même manière que xargs construit ses lignes de commande. Une seule instance de ‘{}’ est autorisée dans la commande. La commande est exécutée dans le répertoire de départ.

donc la façon dont je le comprends, \; exécute des commandes séparées et + ajoute chaque nom. c’est fondamentalement la façon dont il est exécuté, comme le \

 ls testdir1; ls testdir2 

contre

 ls testdir1 testdir2 

Faire ce qui précède dans mon shell reflète le résultat de votre question.

MISE À JOUR 2

Alors, pourquoi voulez-vous utiliser +

dis que j’ai deux fichiers 1.tmp et 2.tmp

1.tmp :

1
2
3

2.tmp :

0
2
3

fonctionnement

  find *.tmp -exec diff {} \; > diff: missing operand after `1.tmp' > diff: Try `diff --help' for more information. > diff: missing operand after `2.tmp' > diff: Try `diff --help' for more information. 

où si vous utilisez + et concaténez les résultats de la recherche comme ceci:

 find *.tmp -exec diff {} \+ 1c1,3 < 1 --- > 0 > 2 > 30 

donc dans ce cas c’est la différence entre diff 1.tmp; diff 2.tmp et diff 1.tmp 2.tmp

Il y a des cas où \; est approprié et + sera nécessaire. L’utilisation de + avec rm en est un exemple: si vous supprimez un grand nombre de fichiers, la vitesse est nettement supérieure. J’aime toujours en apprendre davantage sur find, c’est un outil tellement puissant et pratique que j’espère que cela suffit pour expliquer les différences.

Voici le deal: find a une syntaxe spéciale. Vous utilisez le {} tel quel car ils ont un sens à trouver comme chemin du fichier trouvé et (la plupart) les interpréteurs ne l’interprètent pas autrement. Vous avez besoin de la barre oblique inverse \; parce que le point-virgule a un sens pour le shell, qui le mange avant que find ne puisse l’obtenir. Donc, ce que la recherche veut voir après que le shell est fait, dans la liste des arguments transmis au programme C, est

“-exec”, “rm”, “{}”, “;”

mais vous avez besoin de \; sur la ligne de commande pour obtenir un point-virgule à travers le shell pour les arguments.

Vous pouvez vous en tirer avec \{\} car l’interprétation de \{\} guillemets est juste {} . De même, vous pouvez utiliser ‘{}’.

Ce que vous ne pouvez pas faire, c’est utiliser

  -exec 'rm {} ;' 

parce que le shell interprète cela comme un argument,

“-exec”, “rm {};”

et “rm {};” n’est pas le nom d’une commande. (Au moins à moins que quelqu’un soit vraiment en train de foirer.)

Mettre à jour

la différence est entre

 $ ls file1 $ ls file2 

et

 $ ls file1 file2 

Le + regroupe les noms sur une ligne de commande.

La différence entre ; (point-virgule) ou + (signe plus) -exec comment les arguments sont transmis au paramètre -exec / -execdir . Par exemple:

  • utiliser ; exécutera plusieurs commandes (séparément pour chaque argument),

    Exemple:

     $ find /etc/rc* -exec echo Arg: {} ';' Arg: /etc/rc.common Arg: /etc/rc.common~previous Arg: /etc/rc.local Arg: /etc/rc.netboot 

    Tous les arguments suivants à find sont considérés comme des arguments pour la commande.

    La chaîne {} est remplacée par le nom de fichier en cours de traitement.

  • Utiliser + exécutera les commandes les moins possibles (car les arguments sont combinés). C’est très similaire au fonctionnement de la commande xargs , elle utilisera donc autant d’arguments par commande que possible pour éviter de dépasser la limite maximale d’arguments par ligne.

    Exemple:

     $ find /etc/rc* -exec echo Arg: {} '+' Arg: /etc/rc.common /etc/rc.common~previous /etc/rc.local /etc/rc.netboot 

    La ligne de commande est créée en ajoutant chaque nom de fichier sélectionné à la fin.

    Une seule instance de {} est autorisée dans la commande.

Voir également:

  • man find
  • Utiliser un point-virgule (;) vs plus (+) avec exec dans find à SO
  • Commande unix simple, quelle est la {} et \; pour chez SO
  • Quelle est la signification de {} + dans la commande -exec de find? chez Unix

nous essayions de trouver un fichier pour le ménage.

trouver . -exec echo {} \; la commande a fini la nuit à la fin aucun résultat.

trouver . -exec echo {} \ + a des résultats et n’a pris que quelques heures.

J’espère que cela t’aides.