Pourquoi y a-t-il une différence de sortie entre l'utilisation
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é par un exemple. Disons que find
affiche ces fichiers:
file1
file2
file3
En utilisant -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 comme 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.
Jusqu'à présent, toutes les réponses sont correctes. Je propose cela comme une démonstration plus claire (pour moi) 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 objet 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 transmis 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 s’étouffe sur le nombre d’arguments.
de l'homme
-exec commande;
Exécuter la commande; true si l'état 0 est renvoyé. Tous les arguments suivants à rechercher sont considérés comme des arguments de la commande jusqu'à ce qu'un argument composé de ';' est rencontré. La chaîne '{}' est remplacée par le nom de fichier actuel en cours de traitement partout où il apparaît dans les arguments de la commande, pas seulement dans les arguments où il est seul, comme dans certaines versions de find. Ces deux constructions peuvent avoir besoin d'être échappées (avec un '\') ou citées pour les protéger de l'expansion 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 existe des problèmes de sécurité inévitables entourant l'utilisation de l'option -exec; vous devez plutôt utiliser l'option -execdir.
-exec commande {} +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 à la fin chaque nom de fichier sélectionné; le nombre total d'appels de la commande sera bien inférieur au 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 comme je le comprends, \; exécute des commandes séparées et + ajoute chaque nom. son essentiellement la façon dont il est exécuté, comme le\est une fuite donc son
ls testdir1; ls testdir2
contre
ls testdir1 testdir2
faire ce qui précède dans mon Shell reflète la sortie de votre question.
MISE À JOUR 2
Alors, pourquoi voudriez-vous utiliser +
dis que j'ai deux fichiers 1.tmp et 2.tmp
1.tmp:
1
2
3
2.tmp:
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
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, où si vous supprimez un grand nombre de fichiers, la vitesse est bien meilleure que. J'aime toujours en savoir plus sur la recherche, c'est un outil si puissant et pratique que j'espère que cela suffit pour expliquer les différences.
Voici l'affaire: find a une syntaxe spéciale. Vous utilisez le {}
tels qu'ils sont car ils ont un sens à trouver car le chemin d'accès du fichier trouvé et (la plupart) des shells ne les interprètent pas autrement. Vous avez besoin de la barre oblique inversée \;
parce que le point-virgule a une signification pour le Shell, qui le mange avant que find puisse l'obtenir. Donc ce que trouve veut voir APRÈS que le Shell soit fait, dans la liste des arguments passée au programme C, est
"-exec", "rm", "{}", ";"
mais vous avez besoin de \;
sur la ligne de commande pour obtenir un point-virgule via le shell vers les arguments.
Vous pouvez vous en sortir avec \{\}
parce que l'interprétation citée par Shell de \{\}
est juste {}
. De même, vous pouvez utiliser '{}'.
Ce que vous ne pouvez pas faire est d'utiliser
-exec 'rm {} ;'
car le shell l'interprète comme un argument,
"-exec", "rm {};"
et "rm {};" n'est pas le nom d'une commande. (Du moins, à moins que quelqu'un ne tourne vraiment autour.)
Mise à jour
la différence est entre
$ ls file1
$ ls file2
et
$ ls file1 file2
Le + caténate les noms sur une ligne de commande.
La différence entre ;
(point-virgule) ou +
(signe plus) est la façon dont les arguments sont passés dans -exec
/-execdir
paramètre. Par exemple:
en utilisant ;
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 de
find
sont considérés comme des arguments de la commande.La chaîne
{}
est remplacé par le nom du fichier en cours de traitement.
en utilisant +
exécutera le moins de commandes possibles (car les arguments sont combinés ensemble). C'est très similaire au fonctionnement de la commande xargs
, donc elle utilisera 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 à la fin chaque nom de fichier sélectionné.
Une seule instance de
{}
est autorisé dans la commande.
Voir également: