Як я можу знайти файли та використати 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/ \;
будьте

Будь ласка, напишіть як відповідь, щоб побачити голоси, якщо ви не заперечуєте :)
Michael Durrant

Просто запитав вашу причину, оскільки я відчував, що я не зрозумів. Якщо Драв Слоун додасть замітку про маються на увазі варіанти, його відповідь буде настільки ж хорошим, як найкраще, що я міг написати. Так що краще піти з цим.
манатура

можливий дублікат Find pattern and move
slm

@manatwork Я відредагував свою відповідь, щоб відобразити ці точки дурень :)
Драв Слоан

Відповіді:


43

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

Ви можете скористатися -Iопцією xargs:

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

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

Однак, як вказувало манатурка, детально описана на xargsсторінці "man":

   -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аргументу xargs GNU і 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, можливо, 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/ {} \;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.