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.