web-dev-qa-db-fra.com

Comment puis-je trouver des fichiers et ensuite utiliser xargs pour les déplacer?

Je veux trouver des fichiers et les déplacer.

Je peux trouver le fichier avec:

$ find /tmp/ -ctime -1 -name x*

J'ai essayé de les déplacer vers mon ~/play répertoire avec:

$ find /tmp/ -ctime -1 -name x* | xargs mv ~/play/

mais cela n'a pas fonctionné. Evidemment mv a besoin de deux arguments.
Vous ne savez pas si (ou comment) faire référence à l'élément actuel de xargs dans la commande mv?

31
Michael Durrant

Regardez la réponse de Stéphane pour la meilleure méthode, regardez ma réponse pour des raisons de ne pas utiliser les solutions les plus évidentes (et les raisons pour lesquelles elles ne sont pas les plus efficaces).

Vous pouvez utiliser l'option -I De xargs:

find /tmp/ -ctime -1 -name "x*" | xargs -I '{}' mv '{}' ~/play/

Qui fonctionne dans un mécanisme similaire à find et {}. Je citerais également votre argument -name (Car un fichier commençant par x dans le répertoire actuel serait globalisé et passé en argument à rechercher - ce qui ne donnera pas le comportement attendu!) .

Cependant, comme le souligne manatwork, comme détaillé dans la page de manuel xargs:

   -I replace-str
          Replace occurrences of replace-str in the initial-arguments with
          names read from standard input.  Also, unquoted  blanks  do  not
          terminate  input  items;  instead  the  separator is the newline
          character.  Implies -x and -L 1.

La chose importante à noter est que -L 1 Signifie qu'un seul ligne de sortie de find sera traité à la fois. Cela signifie que c'est syntaxiquement le même que:

find /tmp/ -ctime -1 -name "x*" -exec mv '{}' ~/play/

(qui exécute une seule opération mv pour chaque fichier).

Même en utilisant l'argument xargs GNU -0 Et l'argument find -print0 Provoque exactement le même comportement de -I - c'est la fonction clone() un processus pour chaque fichier mv:

find . -name "x*" -print0 | strace xargs -0 -I '{}' mv '{}' /tmp/other

.
.
read(0, "./foobar1/xorgslsala11\0./foobar1"..., 4096) = 870
mmap(NULL, 135168, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =     0x7fbb82fad000
open("/usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=26066, ...}) = 0
mmap(NULL, 26066, PROT_READ, MAP_SHARED, 3, 0) = 0x7fbb82fa6000
close(3)                                = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,         child_tidptr=0x7fbb835af9d0) = 661
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 661
--- SIGCHLD (Child exited) @ 0 (0) ---
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,         child_tidptr=0x7fbb835af9d0) = 662
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 662
--- SIGCHLD (Child exited) @ 0 (0) ---
.
.
.
47
Drav Sloan

Avec les outils GNU:

find /tmp/ -ctime -1 -name 'x*' -print0 |
  xargs -r0 mv -t ~/play/

Le -t (--target) est GNU spécifique. -print0, -r, -0, bien que non standard et originaire de GNU se trouvent également dans certaines autres implémentations comme sur certains BSD.

POSIX:

find /tmp/ -ctime -1 -name 'x*' -exec sh -c '
  exec mv "$@" ~/play/' sh {} +

Les deux exécutent aussi peu de commandes mv que nécessaire et fonctionnent quels que soient les caractères que les noms de fichiers peuvent contenir. L'option GNU peut avoir l'avantage que find continue de rechercher des fichiers pendant que mv commence à déplacer le premier lot.

Attention, tous les fichiers et répertoires se retrouveront dans un seul répertoire, attention aux conflits si plusieurs fichiers dans des répertoires différents portent le même nom.

18
Stéphane Chazelas

Peut-être que cette commande est possible maintenant et n'était pas de retour en 2013, mais cela fonctionne parfaitement pour moi:

ls pattern* | xargs mv -t DESTINATION/

Le -t la touche place le dossier de destination en premier, libérant la commande mv pour avoir tous les derniers arguments comme seulement les fichiers à déplacer.

4
Nikhil VJ

Vous pouvez essayer avec la commande ci-dessous et testé et cela a bien fonctionné

find /tmp/ -ctime -1 -type f -name "x*" -exec mv -t ~/play/ {} \;
0
Praveen Kumar BS