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?
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) ---
.
.
.
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.
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.
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/ {} \;