J'ai rencontré le même problème sur Mac OSX , en utilisant un ZSH shell :dans ce cas, il n'y a pas de -t
option pour mv
, j'ai donc dû trouver une autre solution. Cependant, la commande suivante a réussi :
find .* * -maxdepth 0 -not -path '.git' -not -path '.backup' -exec mv '{}' .backup \;
Le secret était de citer les accolades . Pas besoin que les accolades soient à la fin du exec
commande.
J'ai testé sous Ubuntu 14.04 (avec BASH et ZSH shells), cela fonctionne de la même manière.
Cependant, lors de l'utilisation du +
signe, il semble bien qu'il doive être à la fin du exec
commande.
La page de manuel (ou le manuel GNU en ligne) explique à peu près tout.
trouver -exec commande {} \;
Pour chaque résultat, command {}
est exécuté. Toutes les occurrences de {}
sont remplacés par le nom du fichier. ;
est préfixé par une barre oblique pour empêcher le shell de l'interpréter.
commande find -exec {} +
Chaque résultat est ajouté à command
et exécuté ensuite. En tenant compte des limitations de longueur de commande, je suppose que cette commande peut être exécutée plusieurs fois, avec la page de manuel qui me soutient :
le nombre total d'invocations de la commande sera bien inférieur au nombre de fichiers correspondants.
Notez cette citation de la page de manuel :
La ligne de commande est construite de la même manière que xargs construit ses lignes de commande
C'est pourquoi aucun caractère n'est autorisé entre {}
et +
sauf pour les espaces blancs. +
fait find détecter que les arguments doivent être ajoutés à la commande comme xargs
.
La solution
Heureusement, l'implémentation GNU de mv
peut accepter le répertoire cible comme argument, avec soit -t
ou le paramètre plus long --target
. Son utilisation sera :
mv -t target file1 file2 ...
Votre find
commande devient :
find . -type f -iname '*.cpp' -exec mv -t ./test/ {} \+
À partir de la page de manuel :
-exec commande;
Exécutez la commande ; true si le statut 0 est renvoyé. Tous les arguments suivants à rechercher sont considérés comme des arguments de 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ù 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 entre guillemets 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'action -exec; vous devriez utiliser l'option -execdir à la place.
-exec commande {} +
Cette variante de l'action -exec exécute la commande spécifiée sur les fichiers sélectionnés, mais la ligne de commande est construite en ajoutant chaque nom de fichier sélectionné à la fin ; le nombre total d'invocations 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.
L'équivalent standard de find -iname ... -exec mv -t dest {} +
pour find
implémentations qui ne prennent pas en charge -iname
ou mv
implémentations qui ne prennent pas en charge -t
consiste à utiliser un shell pour réorganiser les arguments :
find . -name '*.[cC][pP][pP]' -type f -exec sh -c '
exec mv "[email protected]" /dest/dir/' sh {} +
En utilisant -name '*.[cC][pP][pP]'
, nous évitons également de dépendre des paramètres régionaux actuels pour décider quelle est la version majuscule de c
ou p
.
Notez que +
, contrairement à ;
n'est pas spécial dans un shell et n'a donc pas besoin d'être entre guillemets (bien que les guillemets ne nuisent pas, sauf bien sûr avec des shells comme rc
qui ne prennent pas en charge \
en tant qu'opérateur de cotation).
Le /
de fin en /dest/dir/
est tel que mv
échoue avec une erreur au lieu de renommer foo.cpp
à /dest/dir
dans le cas où un seul cpp
le fichier a été trouvé et /dest/dir
n'existait pas ou n'était pas un répertoire (ou un lien symbolique vers le répertoire).