Linux: выполнить команду для каждого скопированного файла

275
goweon

Каков наилучший способ скопировать файлы в новое место при выполнении команды для каждого скопированного файла? Предполагается, что скопированные папки будут иметь подкаталоги.

Например, вы можете сделать cp -Rдля общего ресурса или rsyncдля резервного копирования, и вы хотите:

  • перекодировать видео: ffmpeg -i $source -c:v libx264 -crf 23 -c:a copy $destination
  • компресс для архива: gzip -9 $source
  • шифровать для транспорта: gpg -e -r USER@example.com $source
  • только копии заголовков для предварительного просмотра: head -n 10 $source > $destination
  • или даже цепочка нескольких команд
0

1 ответ на вопрос

0
Kamil Maciorowski

Первым шагом было бы скопировать структуру каталогов:

sdir="/path/to/source/dir" tdir="/path/to/target/dir" cd "$sdir" find . -type d -exec mkdir -p "$tdir"/{} \; 

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

find . -type d -exec chmod --reference={} "$tdir"/{} \; 

(Примечание: --referencePOSIX не требуется).

Или вместо mkdirвас можно использовать cp -a --attributes-only(также не POSIX):

# this assumes $tdir doesn't yet exist but its future parent does cp -a "$sdir" "$tdir" 

затем удалите все не-каталоги $tdir, оставив пустую структуру каталогов:

# make sure "$tdir" is what it should be find "$tdir" ! -type d -delete 

Теперь, когда у вас есть целевая структура каталогов, работайте с файлами. Если вам не нужны каналы, перенаправления и т. Д., Этот примерный подход подойдет:

cd "$sdir" find . -type f -exec ffmpeg -i {} -c:v libx264 -crf 23 -c:a copy "$tdir"/{} \; # source ^^ target ^^^^^^^^^^ 

Если вам нужны каналы или перенаправления, вам понадобится оболочка для их обработки:

cd "$sdir" find . -type f -exec sh -c 'head -n 10 "$1" >"$2"/"$1"' sh-find {} "$tdir" \; # for sh these are $0:^^^^^^^, $1:^^, $2:^^^^^ 

Запуск отдельной оболочки для каждого файла медленен, но позволяет вам делать практически все, что угодно.

Похожие вопросы