Je recherche des fichiers dont le nom contient AAA
dans leur chemin en utilisant la commande suivante:
find path_A -name "*AAA*"
Étant donné la sortie affichée par la commande ci-dessus, je souhaite déplacer ces fichiers vers un autre chemin, par exemple path_B
. Au lieu de déplacer ces fichiers un par un, puis-je optimiser la commande en déplaçant ces fichiers juste après la commande find?
Avec GNU mv :
find path_A -name '*AAA*' -exec mv -t path_B {} +
Cela utilisera l'option -exec
De find qui remplace le {}
Avec chaque résultat de recherche à son tour et exécute la commande que vous lui donnez. Comme expliqué dans man find
:
-exec command ;
Execute command; true if 0 status is returned. All following
arguments to find are taken to be arguments to the command until
an argument consisting of `;' is encountered.
Dans ce cas, nous utilisons la version +
De -exec
Afin d'exécuter le moins d'opérations mv
possible:
-exec command {} +
This variant of the -exec action runs the specified command on
the selected files, but the command line is built by appending
each selected file name at the end; the total number of invoca‐
tions of the command will be much less than the number of
matched files. The command line is built in much the same way
that xargs builds its command lines. Only one instance of `{}'
is allowed within the command. The command is executed in the
starting directory.
Vous pouvez également faire quelque chose comme ci-dessous.
find path_A -name "*AAA*" -print0 | xargs -0 -I {} mv {} path_B
Où,
-0
S'il y a des espaces ou des caractères vides (y compris les retours à la ligne), de nombreuses commandes ne fonctionneront pas. Cette option prend soin des noms de fichiers avec un espace vide.-I
Remplacez les occurrences de replace-str dans les arguments initiaux par des noms lus à partir de l'entrée standard. De plus, les espaces non entre guillemets ne terminent pas les éléments d'entrée; à la place, le séparateur est le caractère de nouvelle ligne.Test
J'ai créé deux répertoires comme sourcedir
et destdir
. Maintenant, j'ai créé un tas de fichiers dans sourcedir
en tant que file1.bak
, file2.bak
et file3 with spaces.bak
Maintenant, j'ai exécuté la commande comme,
find . -name "*.bak" -print0 | xargs -0 -I {} mv {} /destdir/
Maintenant, à l'intérieur de destdir
, quand je fais ls
, je pouvais voir que les fichiers étaient passés de sourcedir
à destdir
.
Références
http://www.cyberciti.biz/faq/linux-unix-bsd-xargs-construct-argument-lists-utility/
Pour le bénéfice des utilisateurs d'OS X rencontrant cette question, la syntaxe dans OS X est légèrement différente. En supposant que vous ne vouliez pas effectuer de recherche récursive dans les sous-répertoires de path_A
:
find path_A -maxdepth 1 -name "*AAA*" -exec mv {} path_B \;
Si vous souhaitez rechercher récursivement tous les fichiers dans path_A
:
find path_A -name "*AAA*" -exec mv {} path_B \;
Le -exec
est la meilleure façon de procéder. Si, pour une raison quelconque, ce n'est pas une option, vous pouvez également lire les résultats dans une boucle:
find path_A -name "*AAA*" -print0 |
while IFS= read -r -d $'\0' file; do mv "$file" path_B; done
C'est le moyen sûr, il peut traiter les noms de fichiers qui contiennent des espaces, des nouvelles lignes ou d'autres caractères étranges. Une manière plus simple, mais qui échoue à moins que vos noms de fichiers ne soient composés que de caractères alphanumériques simples, est
mv $(find path_A -name "*AAA*") path_B
Mais utilisez la boucle while.
Utiliser uniquement fonctionnalités POSIX de find
(et également de mv
):
find path_A -name '*AAA*' -exec sh -c 'mv "$@" path_B' find-sh {} +
Lectures complémentaires:
Autrement
for f in `find path_A -name "*AAA*"`; do mv $f /destination/dir/; done