Déplacer des fichiers avec find + xargs: la cible n'est pas un répertoire?

9

Lorsque j'exécute la commande suivante:

> mkdir some_dir
> find /foo/bar/ -name '*.csv' -print0 | xargs -0 mv {} some_dir

Je reçois des centaines de lignes qui disent:

mv: target `/foo/bar/XX.csv` is not a directory

Pourquoi? Je pensais que xargs exécuterait:

mv /foo/barXX.csv some_dir

pour chaque fichier findtrouvé. Que se passe-t-il? Au fait, c'est avec zsh

Mise à jour:

Update1:

J'ai essayé:

find /foo/bar/ -name '*.csv' -print0 | xargs -0 mv {} -t some_dir

mais j'ai eu quelques lignes comme:

mv: cannot stat `{}': No such file or directory

bien que je pense que la commande déplace correctement mes fichiers.

Update2:

Je ne semble pas avoir besoin de l' -toption lorsque j'utilise mvseul. Par exemple

> touch file1.txt
> touch file2.txt
> mkdir my_dir
> mv  file1.txt  file2.txt  my_dir

fonctionne bien. Pourquoi ai-je besoin -tlors de l'utilisation xargs?

Amelio Vazquez-Reina
la source

Réponses:

14

En supposant que vous avez GNU ( find, xargs, & mv), changer votre commande à ceci:

$ find /foot/bar/ -name '*.csv' -print0 | xargs -0 mv -t some_dir

extrait de la mvpage de manuel

   -t, --target-directory=DIRECTORY
          move all SOURCE arguments into DIRECTORY

Ce qui précède xargs ...construira la commande pour que les appels à se déplacer soient comme ceci:

 $ mv 1.csv 2.csv 3.csv ... -t some_dir

Pas besoin de xargs

Vous pouvez ignorer cette approche en faisant findsimplement tout le travail lui-même:

$ find /foot/bar/ -name '*.csv' -exec mv -t some_dir {} +

Pourquoi avez-vous besoin du mv -t ...?

Cela a à voir avec la façon dont xargsest construit l'ensemble de fichiers à passer à la commande qu'il va exécuter à chaque fois (c'est-à-dire mv ...).

Lorsque vous exécutez la mvcommande manuellement vous-même, vous contrôlez le nombre de noms de fichiers qui lui sont transmis et vous n'avez donc pas à vous soucier d'avoir besoin du -t my_dircar vous placerez toujours le répertoire de destination en dernier.

Références

slm
la source
Merci! C'est très utile. Je suis un peu confus cependant (voir mes mises à jour)
Amelio Vazquez-Reina
1
La commande construite est mv -t some_dir 1.csv 2.csv 3.csv ...donc la dernière argumentation du fichier. C'est l'erreur dans la question, pour l'utiliser, {}vous devez passer -I {}à xargs.
frostschutz
Merci. Cela explique tout. Qu'en est-il de la deuxième question que j'avais dans la mise à jour 2? Savez-vous pourquoi je n'ai pas besoin -tde plusieurs fichiers et d'un répertoire avec un régulier mv?
Amelio Vazquez-Reina
1
@ user815423426 - Je le mettrai à jour plus tard quand j'aurai l'occasion ce soir, je sais pourquoi.
slm
@ user815423426 - J'ai mis à jour la question, faites-moi savoir si cela a du sens par rapport à mv -t.
slm
1

Vous pouvez également utiliser la commande ls au lieu de la commande find:

ls /foot/bar/*.csv | xargs  mv -t some_dir
Luis Ángel Rodríguez
la source