Як інтегрувати команду mv після команди find?


60

Я шукаю файли, ім'я яких містяться AAAв їх шляху, використовуючи наступну команду:

find path_A -name "*AAA*"

Враховуючи результат, показаний вищевказаною командою, я хочу перемістити ці файли в інший шлях, скажімо path_B. Замість того, щоб переміщувати ці файли по одному, чи можу я оптимізувати команду, переміщуючи ці файли відразу після команди find?

Відповіді:


86

З GNU mv :

find path_A -name '*AAA*' -exec mv -t path_B {} +

Для цього буде використана -execопція find, яка {}по черзі замінює результат кожного знаходження та виконує команду, яку ви йому надаєте. Як пояснено в man find:

   -exec command ;
          Execute  command;  true  if 0 status is returned.  All following
          arguments to find are taken to be arguments to the command until
          an  argument  consisting of `;' is encountered.  

У цьому випадку ми використовуємо +версію, -execщоб ми виконали якомога менше mvоперацій:

   -exec command {} +
          This  variant  of the -exec action runs the specified command on
          the selected files, but the command line is built  by  appending
          each  selected file name at the end; the total number of invoca‐
          tions of the command will  be  much  less  than  the  number  of
          matched  files.   The command line is built in much the same way
          that xargs builds its command lines.  Only one instance of  `{}'
          is  allowed  within the command.  The command is executed in the
          starting directory.

Не забувайте "\;" наприкінці exec!
Чарльз Рот

@Charles Roth: це те, +що виконує завдання, ви можете прочитати мою цитату вище або man findзамість цього
cuonglm

Дякую за це! Я намагався використовувати, -exec mv {} path_b +і це не вдалося з помилками дозволів. ТБХ, я досі не розумію чому, але -exec mv -t path_b {} +працює частування!
Джеремі Девіс

6
@JeremyDavis При використанні обов'язкове -exec ... {} +значення {}має бути останньою справою перед +. Ось чому він використовує, mv -t destdir {} +а ні mv {} destdir +. -exec mv {} destdir ';'Замість цього використано один холод , але він би виконувався mvодин раз для кожного файлу.
Кусалаланда

23

Ви можете зробити щось на кшталт нижче.

find path_A -name "*AAA*" -print0 | xargs -0 -I {} mv {} path_B

Де,

  1. -0Якщо є пробіли або символи (включаючи нові рядки), багато команд не працюватимуть. Цей параметр приймає піклування про імена файлів із порожнім пробілом.
  2. -IЗамініть випадки заміщення str в початкових аргументах іменами, прочитаними зі стандартного вводу. Крім того, пропуски без котирування не закінчують елементи введення; натомість роздільник - символ нового рядка.

Тестування

Я створив два каталоги як sourcedirі destdir. Тепер я створив купу файлів всередині sourcedirяк file1.bak, file2.bakіfile3 with spaces.bak

Тепер я виконав команду як

find . -name "*.bak" -print0 | xargs -0 -I {} mv {} /destdir/

Тепер, всередині destdir, коли я роблю ls, я міг бачити , що файли переміщені з sourcedirв destdir.

Список літератури

http://www.cyberciti.biz/faq/linux-unix-bsd-xargs-construct-argument-lists-utility/


22

На користь користувачів ОС X, які стикаються з цим питанням, синтаксис в OS X дещо інший. Припустимо, що ви не хочете рекурсивно здійснювати пошук у підкаталогах path_A:

find path_A -maxdepth 1 -name "*AAA*" -exec mv {} path_B \;

Якщо ви хочете шукати всі файли рекурсивно в path_A:

find path_A -name "*AAA*" -exec mv {} path_B \;

Це не специфічний для синтаксису ОС X, він однаковий з будь-яким findя використовував. Хороші моменти: -maxdepth(особливо якщо path_B є підкаталогом - уникає mvспроб переміщення файлів, які вже є!) Та використання \; (тому {} не повинен бути останнім параметром, і звичайний mvсинтаксис можна використовувати)
drevicko

6

-execЦе кращий спосіб зробити це. Якщо з будь-якої причини це не варіант, ви також можете прочитати результати в циклі:

find path_A -name "*AAA*" -print0 | 
    while IFS= read -r -d $'\0' file; do mv "$file" path_B; done

Це безпечний спосіб, він може мати справу з іменами файлів, які містять пробіли, нові рядки або інші дивні символи. Більш простий спосіб, але той, який не вдається, якщо назви ваших файлів не складаються лише з простих буквено-цифрових символів , є

mv $(find path_A -name "*AAA*") path_B

Але використовуйте цикл while.


your file names consist only of simple alphanumeric charactersARG_MAX


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.