Je veux savoir exactement ce que {} \;
et {} \+
et | xargs ...
faire. Veuillez les clarifier avec des explications.
En dessous de 3 commandes s'exécutent et produisent le même résultat, mais la première commande prend un peu de temps et le format est également un peu différent.
find . -type f -exec file {} \;
find . -type f -exec file {} \+
find . -type f | xargs file
C'est parce que le premier exécute la file
commande pour chaque fichier provenant de la find
commande. Donc, fondamentalement, il fonctionne comme:
file file1.txt
file file2.txt
Mais les 2 derniers trouvent avec les -exec
commandes exécutez la commande de fichier une fois pour tous les fichiers comme ci-dessous:
file file1.txt file2.txt
Ensuite, j'exécute les commandes suivantes sur lesquelles la première s'exécute sans problème mais la seconde donne un message d'erreur.
find . -type f -iname '*.cpp' -exec mv {} ./test/ \;
find . -type f -iname '*.cpp' -exec mv {} ./test/ \+ #gives error:find: missing argument to `-exec'
Pour la commande avec {} \+
, cela me donne le message d'erreur
find: missing argument to `-exec'
pourquoi donc? quelqu'un peut-il expliquer ce que je fais de mal?
Réponses:
La page de manuel (ou le manuel GNU en ligne ) explique à peu près tout.
commande find -exec {} \;
Pour chaque résultat,
command {}
est exécuté. Toutes les occurrences de{}
sont remplacées par le nom de fichier.;
est précédé d'une barre oblique pour empêcher le shell de l'interpréter.commande find -exec {} +
Chaque résultat est ajouté
command
et exécuté par la suite. En tenant compte des limitations de longueur de commande, je suppose que cette commande peut être exécutée plus de fois, avec la page de manuel me soutenant:Notez cette citation de la page de manuel:
C'est pourquoi aucun caractère n'est autorisé entre
{}
et à l'+
exception des espaces.+
fait que find détecte que les arguments doivent être ajoutés à la commande commexargs
.La solution
Heureusement, l'implémentation GNU de
mv
peut accepter le répertoire cible comme argument, avec l'un-t
des paramètres ou le paramètre le plus long--target
. Son utilisation sera:Votre
find
commande devient:Depuis la page de manuel:
la source
./test/
entre{}
et+
, mais aucun caractère non blanc n'est autorisé entre ceux-ci.+
commande AFAIU est un peu étrange car elle colle les fichiers à «la fin» (et non à la place de{}
) alors pourquoi utiliser{}
du tout - c'est déroutant. Merci pour l'-t
option que je ne connaissais pas, il semble que cette option ait été créée pour contourner ce-exec +
problème!J'ai rencontré le même problème sur Mac OSX , en utilisant un shell ZSH : dans ce cas, il n'y a pas d'
-t
option pourmv
, donc j'ai dû trouver une autre solution. Cependant, la commande suivante a réussi:Le secret était de citer les accolades . Pas besoin que les accolades soient à la fin de la
exec
commande.J'ai testé sous Ubuntu 14.04 (avec les shells BASH et ZSH ), cela fonctionne de la même manière.
Cependant, lors de l'utilisation du
+
signe, il semble bien que ce soit à la fin de laexec
commande.la source
{}
doit être cité dans les coquillesfish
etrc
, mais pas danszsh
,bash
ni dans les autres coquilles des familles Bourne ou csh.bash
, en effet les citations ne sont pas nécessaires. Curieusement, j'ai eu un problème si je ne les citais pas sous MacOS (en utilisantzsh
). Mais je n'ai pas de Mac à portée de main pour réessayer ...L'équivalent standard de
find -iname ... -exec mv -t dest {} +
pour lesfind
implémentations qui ne prennent pas en charge-iname
ou lesmv
implémentations qui ne prennent pas en charge-t
est d'utiliser un shell pour réorganiser les arguments:En utilisant
-name '*.[cC][pP][pP]'
, nous évitons également de nous fier aux paramètres régionaux actuels pour décider quelle est la version majuscule dec
oup
.Notez que
+
, contrairement à ce;
n'est pas spécial dans aucun shell, il n'a donc pas besoin d'être cité (bien que les guillemets ne nuiront pas, sauf bien sûr avec des shells commerc
celui-ci ne sont pas pris en charge\
comme opérateur de guillemets).La fuite
/
en/dest/dir/
est ainsi quemv
échoue avec une erreur au lieu de renommerfoo.cpp
à/dest/dir
dans le cas où un seulcpp
fichier a été trouvé et/dest/dir
n'existait ou non un répertoire (ou symlink dans le répertoire).la source
la source
non, la différence entre
+
et\;
doit être inversée.+
ajoute les fichiers à la fin de la commande exec, puis exécute la commande exec et\;
exécute la commande pour chaque fichier.Le problème est
find . -type f -iname '*.cpp' -exec mv {} ./test/ \+
qu'ilfind . -type f -iname '*.cpp' -exec mv {} ./test/ +
ne devrait pas être nécessaire d'y échapper ou de mettre fin au+
xargs Je n'ai pas utilisé depuis longtemps mais je pense que ça marche comme +.
la source
-name "*.cpp"
J'utilise à peine -iname à moins que je ne veuille faire une recherche regex difficile, comme -iname '??? work. * \. Cpp'-iname
et-name
.-iname
est la version insensible à la casse de-name
et n'a pas de différences dans la gestion des expressions régulières. Je suggère d'essayer les commandes avant de publier, votre commande échoue également dans mon shell.