Linux: Скопіюйте всі файли, що відповідають шаблону, з dir та subdir, в один dir


31

Якби я хотів , щоб скопіювати всі *.soфайли з srcв dstя зроблю:

cp src/*.so dst

Тим НЕ менше, я хочу , щоб скопіювати всі *.soфайли з СРКА і це підкаталоги в dst. Будь-які підказки?

Відповіді:


36

Спробуйте:

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

17
findможе робити узгодження шаблонів та виконувати команди. Немає необхідності передавати його вихід:find src/ -type f -name '*.so' -exec cp '{}' dst/ ';'
1111

1
Так, але, однак, часто простіше читати конвеєр, а також можливості відповідності шаблонів grepзначно переважають прості шаблони оболонок, використовувані в -nameпараметрі до find. xargsтакож набагато потужніший, ніж -execпараметр для find.
Майк Інш

2
Рішення @jaquer набагато краще, оскільки на MacOSX утиліта xargs не має опції -i. Але його рішення працює як шарм.
Біалікс

Я боровся з повідомленням про помилку на аргументі -i xargs, поки я не прочитав коментар від @bialix щодо рішення Jaquer, який прекрасно працював на моєму Mac. Дякую
svannoy

Чи створить це підкаталоги за потребою?
Леннарт Ролланд

15

Якщо ви використовуєте Bash, ви можете ввімкнути globstar опцію оболонки, щоб відповідати файлам і каталогам рекурсивно:

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

Якщо вам потрібно знайти файли, імена яких починаються з .та / або файли в і під каталогами, імена яких починаються з ., встановіть також dotglobпараметр (наприклад, з shopt -s dotglob). Їх можна встановити в одній команді:

shopt -s globstar dotglob

Не копіює файли у підкаталогах, починаючи з a. на їх ім’я
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.