Используйте xargs для преобразования каталога из результатов поиска в другой каталог


У меня есть следующая команда:

find . -type d -mtime 0 -exec mv {} /path/to/target-dir ;

Это приведет к перемещению каталога, основанного в другой каталог. Как я могу использовать xargs вместо exec, чтобы сделать то же самое.

5 30

5 ответов:

Если у вас есть GNU mvfind и xargs), Вы можете использовать опцию -t для mv-print0 для find и -0 для xargs):

find . -type d -mtime -0 -print0 | xargs -0 mv -t /path/to/target-dir

Обратите внимание, что современные версии find (совместимые с POSIX 2008) поддерживают + вместо ; и ведут себя примерно так же, как xargs без использования xargs:
find . -type d -mtime -0 -exec mv -t /path/to/target-dir {} +

Это позволяет find группировать удобные номера имен файлов (каталогов) в один вызов программы. У вас нет такого уровня контроля по количеству аргументов, переданных в mv, которые предоставляет xargs, но это редко действительно нужно. Это все еще зависит от опции -t для GNU mv.

С BSD xargs (Для OS X и FreeBSD), вы можете использовать -J, который был построен для этого:

find . -name some_pattern -print0 | xargs -0 -J % mv % target_location

, который переместит все, что соответствует some_pattern в . в target_location

С GNU xargs (Для Linux и Cygwin), используйте -I вместо:

find . -name some_pattern -print0 | xargs -0 -I % mv % target_location

Устаревший вариант -i GNU xargs подразумевает -I{} и может использоваться следующим образом:

find . -name some_pattern -print0 | xargs -0 -i mv {} target_location
Обратите внимание, что BSD xargs также имеет опцию -I, но это делает что-то еще.
find ./ -maxdepth 1 -name "some-dir" -type d -print0 | xargs -0r mv -t x/

Найти : при выборе опции -print0 вывод закончится на '\0';

Xargs : с опцией -0, он разделит args на '\0', но пробел, -r означает no-run-if-empty, так что вы не получите никаких ошибок, если find не получил никакого вывода. (-r Является расширением GNU.)

Я обычно использую это в сценариях, когда я не уверен, существуют ли целевые файлы или нет.

find это не очень хороший инструмент для этого. Я полагаю, вы хотите переместить все подкаталоги в другой каталог. find выведет такие вещи, как

./a
./a/b
./a/b/c
./a/b/c/d

После того, как ./a будет перемещен первым, вы просто получите ошибки о "нет такого файла или каталога" все поддиры.

Вы должны просто использовать mv */ /another/place - конечная косая черта на подстановочном знаке ограничивает расширение только dirs.

Если вы не используете GNU mv, вы можете использовать эту команду:

find . -depth -type d -mtime 0 -exec bash -c 'declare -a array;j=1;for i; do array[$j]="$i"; j=$((j+1));done; mv "${array[*]}" /path/to/target-dir' arg0 {} +

В противном случае, вот более простое решение, которое не требует xargs:

find . -depth -type d -mtime 0 -exec mv -t /path/to/target-dir {} +

Обратите внимание, что я добавил-глубина в противном случае вы будете иметь ошибки, когда и каталог и один из его подкаталогов должен быть обработан.