Linux: Скопируйте все файлы, соответствующие шаблону, из каталога dir и его подкаталогов в один каталог.

31

Если бы я хотел скопировать все *.soфайлы из srcв, dstя бы сделал:

cp src/*.so dst

Однако я хочу скопировать все *.soфайлы из src и его подкаталогов в dst. Есть какие-нибудь подсказки?

Альбус Дамблдор
источник

Ответы:

36

Пытаться:

find src/ -type f | grep -i so$ | xargs -i cp {} dst
Майк Инш
источник
17
findможет делать сопоставление с образцом и выполнять команды. Там нет необходимости find src/ -type f -name '*.so' -exec cp '{}' dst/ ';'
транслировать
1
Да, это возможно, однако часто легче читать конвейер, также возможности сопоставления с образцом grepнамного перевешивают простые шаблоны оболочки, используемые в -nameпараметре find. xargsтакже гораздо более мощный, чем -execпараметр find.
Майк Инш
2
Решение @jaquer намного лучше, потому что на MacOSX утилита xargs не имеет опции -i. Но его решение работает как шарм.
Биаликс 12.12.12
Я боролся с сообщением об ошибке аргумента -i для xargs, пока не прочитал комментарий от @bialix относительно решения jaquer, которое отлично работало на моем Mac. Спасибо
сванной
Будет ли это создавать подкаталоги по мере необходимости?
Леннарт Роллан
15

Если вы используете Bash, вы можете включить globstar опцию оболочки для рекурсивного сопоставления файлов и каталогов:

shopt -s globstar
cp src/**/*.so dst

Если вам нужно найти файлы, имена которых начинаются с ., и / или файлы в каталогах и под ними, имена которых начинаются с ., установите эту dotglobопцию (например, с shopt -s dotglob). Вы можете установить их обоих одной командой:

shopt -s globstar dotglob
jáquer
источник
Не копирует файлы в подкаталогах, начиная с. от их имени
rboy
8

Я попробовал команду, предложенную Майком:

find src/ -type f | grep -i so$ | xargs -i cp {} dst

но в итоге все файлы были выгружены в каталог dstс потерянными относительными путями.

Чтобы сохранить относительные пути, команду необходимо изменить следующим образом:

find src/ -type f | grep -i so$ | xargs -i cp {} dst/{}
Илья Друкер
источник
7
+1. Однако это предполагает, что каталоги, соответствующие относительным исходным путям, существуют в dst. Если это не так, используйте cp --parents. Кроме того, не забудьте процитировать имена файлов. Таким образом: ... | xargs -i cp --parents "{}" dst(обратите внимание, что последний аргумент cpтеперь является «просто» целевым каталогом). Команда может быть еще короче (и , вероятно , быстрее) , используя -tфлаг: ... | xargs cp --parents -t dst.
Stephan202
1
@ Stephan202 Я должен был использовать... | xargs cp {} --parents -t dst.
warvariuc
для тех, кто на Mac, --parentsнедоступен. Я использовал dittoвместо него: stackoverflow.com/questions/11246070/cp-parents-option-on-mac
Брайан Янг
3

Еще один способ сделать это так:

find src/ -type f -name "*.so" -exec cp {} dst/ \;
Кириак
источник
И это должно уменьшить количество cpпроцессов: ... -exec cp -t dst/ {} +.
Камиль Мачоровский
Эй, Камил! Спасибо за комментарий! Можете ли вы объяснить мне, как ваше решение делает вещи быстрее! Всегда готов узнать больше :)
Kyriakos
После завершения -execс ;, {}заменяется на один путь , в то время. Вы получаете отдельный cpдля каждого файла. С +синтаксисом findзаменяет {}несколько результатов (вплоть до определенного системой предела длины командной строки; ограничение: {}должно быть последним, что раньше +, следовательно cp -t). Создание и завершение процесса - вещь относительно дорогая. По этой причине это хорошо использовать, +когда вы ожидаете много результатов. В этом случае копирование большого количества файлов в любом случае может занять много времени, поэтому разница может остаться незамеченной; тем не менее, это хорошая практика.
Камиль Мачоровски
1

Grep можно заменить с помощью команды find's -name :

find src/ -type f -name "*.so" | xargs -i cp {} dst/{}
Th. Тилеманн
источник