Как я могу найти файлы и затем использовать xargs для их перемещения?

28

Я хочу найти некоторые файлы, а затем переместить их.

Я могу найти файл с:

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

Я попытался переместить их в мой ~/playкаталог с помощью:

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

но это не сработало. Очевидно, mv нужны два аргумента.
Не уверены, что (или как) ссылаться на текущий элемент xargs в команде mv?

Майкл Даррант
источник
3
Зачем? Вы можете использовать заполнитель с -I:, find . | xargs -I'{}' mv '{}' ~/play/но, как говорит человек, это «подразумевает -xи» -L 1. Так что никакой выгоды. Лучше find . -exec mv '{}' ~/play/ \;
будь
Пожалуйста, напишите в качестве ответа, чтобы увидеть голоса, если вы не возражаете :)
Майкл Даррант
Просто спросил вашу причину, так как у меня было чувство, что я не понял. Если Драв Слоан добавит примечание о предполагаемых вариантах, его ответ будет настолько хорошим, насколько я смог написать. Так что лучше иди с этим.
manatwork
возможный дубликат паттерна Find и move
slm
@manatwork Я отредактировал свой ответ, чтобы отразить эти моменты, чувак :)
Драв Слоан

Ответы:

43

Посмотрите на ответ Стефана за лучший метод, посмотрите на мой ответ по причинам, по которым не используются более очевидные решения (и по причинам, по которым они не являются наиболее эффективными).

Вы можете использовать -Iопцию xargs:

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

Который работает по аналогичному механизму findи {}. Я бы также процитировал ваш -nameаргумент (потому что файл, начинающийся с xданного каталога, будет глобализирован и передан в качестве аргумента для поиска - что не даст ожидаемого поведения!).

Однако, как указано в manatwork, как подробно описано на 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.

Важно отметить, что это -L 1означает, что одновременно обрабатывается только одна строка вывода find. Это означает, что это синтаксически так же, как:

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

(который выполняет одну mvоперацию для каждого файла).

Даже использование -0аргумента GNU xargs и find -print0аргумента приводит к абсолютно одинаковому поведению -I- это clone()процесс для каждого файла 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) ---
.
.
.
Драв Слоан
источник
Это предполагает, что имена файлов не содержат символов новой строки, одинарных кавычек, двойных кавычек или обратной косой черты.
Стефан Шазелас
17

С инструментами GNU:

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

Опция -t( --target) специфична для GNU. -print0, -r, -0, В то время как нестандартное и происходящий в GNU также найдены в некоторых других вариантах реализации , как на некоторых BSDs.

POSIXly:

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

Оба запускают столько mvкоманд, сколько необходимо, и работают с любыми символами, которые могут содержать имена файлов. У GNU one может быть преимущество в том, что он findпродолжает искать файлы, когда mvначинает перемещать первый пакет.

Помните, что все файлы и каталоги окажутся в одном каталоге, остерегайтесь столкновений, если несколько файлов в разных каталогах имеют одинаковые имена.

Стефан Шазелас
источник
Это решение намного эффективнее, так как оно вызывает mvодин раз для всех аргументов (или для всех -Lили -n, если предоставлено). В противном случае вызов mvдля каждого файла быстро устареет (и замедлится).
r2evans
1

Возможно, эта команда возможна сейчас, и ее не было в 2013 году, но она отлично работает для меня:

ls pattern* | xargs mv -t DESTINATION/

В -tключевых путах папки назначения первыми, освободив mvкоманду , чтобы все последние аргументы , как только файлы будут перемещены.

Нихил В.Ю.
источник
1
это было самое простое решение, которое сработало для меня
ptetteh227
0

Вы можете попробовать с приведенной ниже командой и проверено, и она работала нормально

find /tmp/ -ctime -1 -type f -name "x*" -exec mv -t ~/play/ {} \;
Правин Кумар Б.С.
источник