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

Не копирует файлы в подкаталогах, начиная с. от их имени
— 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). Создание и завершение процесса - вещь относительно дорогая. По этой причине это хорошо использовать, +когда вы ожидаете много результатов. В этом случае копирование большого количества файлов в любом случае может занять много времени, поэтому разница может остаться незамеченной; тем не менее, это хорошая практика.
— Камиль Мачоровски

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.