Як я можу рекурсивно копіювати файли за допомогою розширення файлів, зберігаючи структуру каталогу?


71

У командному рядку Linux я хотів би скопіювати (дуже великий) набір .txtфайлів з одного каталогу (та його підкаталогів) в інший.

Мені потрібна структура каталогів, щоб залишатися недоторканою, і мені потрібно ігнорувати файли, крім тих, що закінчуються на .txt.


2
Якщо cp і знайти теги у своєму запитанні, чи означає це, що ви прив’язані до цих варіантів? Оскільки ваш набір даних дуже великий, є сенс припустити, що процес копіювання може перерватися з якихось причин, і вам доведеться перезапустити його. Я не впевнений, що підхід find / cp зможе відновити передачу та скопіювати лише відсутні частини. Якщо ви не прив’язані до пошуку / cp, ви можете розглянути rsync, який розумніший. Опція --exclude дозволить вам пропустити .txt файли.
vtest

Справедливий дзвінок - rsync, ймовірно, є кращим варіантом. Не прив’язаний до знаходження / ср. (Я все-таки використовував їх - rsync не був встановлений на віддаленій машині, це живий веб-сервер. Я хотів залишити якомога менше площі)
незатребуваний багаж

Відповіді:


95

Ви можете використовувати find і cpio для цього

cd /top/level/to/copy
find . -name '*.txt' | cpio -pdm /path/to/destdir

(-updm for overwrite destination content.)

чому м? Я думав, що це просто зберегти дату зміни файлу.
Мубашар

7
cd /source/path
find -type f -name \*.txt -exec install -D {} /dest/path/{} \;

Ви пропускаєте .після find. Також на macOS 10.13.1 це спрацювало:find . -type f -name "*.txt" -exec install -v {} /dest/path/{} \;
похмурий

2

Ще один підхід

find . -name '*.txt' -exec rsync -R {} path/to/dext \;


Мені подобається це рішення. Раніше я find . -iname '*.txt' -exec rsync -Rptgon {} path/to/dext \;робив збіг невідчутливих до справ і зберігав право власності та дозволи.
MountainX

1

Найпростіший спосіб, який працював для мене:

cp --parents -R jobs/**/*.xml ./backup/

один улов - вам доведеться перейти до "потрібного" каталогу раніше, щоб "батьківський шлях" був правильним.

Також переконайтеся, що ви включили рекурсивні глобуси в bash:

shopt -s globstar

1

як щодо того, щоб ви спочатку скопіювали це

cp -r /old/folder /new/folder

потім перейдіть до нової папки та запустіть

find . -type f ! -iname "*.txt" -delete

або просто

cp -r /old/folder /new/folder && find . -type f ! -iname "*.txt" -delete

Редагувати: добре, ви хочете одну команду, яка фільтрує (я цього не перевіряв, оскільки моя система не має cpioкоманди!). Ось де я його знайшов: http://www.gnu.org/software/findutils/manual/html_mono/find.html#Copying-A-Subset-of-Files

find . -name "*.txt" -print0 |
     cpio -pmd0 /dest-dir

Спершу протестуйте це, оскільки я ще цього не пробував. Якщо хтось перевірить, це було б чудово.


Киває ура: це спрацювало б, але без фільтрування до .txt я переглядаю кілька мільйонів файлів (виходить у кілька сотень ГБ). Якщо потрібно, можливо, доведеться, але я хотів би відфільтрувати під час копіювання, якщо це можливо
незатребуваний багаж

1
Ура, відредагована версія працює, якщо я видаляю '0' з -pmd0
незатребуваний

Ви повинні тримати 0в систему -pmd0і додати -print0в кінець findкоманди ( як раз перед |).
G-Man

1

Я намагався зробити те ж саме на macOS, але жоден із варіантів не працював для мене. Поки я не виявив ditto.

Мені довелося скопіювати багато файлів .wav і пропустити відеофайли ... Ось ось що я придумав:

find . -type f -iname "*.wav" -ls -exec ditto {} /destination/folder/{} \;

  • find .- Виконує пошук у поточній папці. переконайтеся, що ви cd /source/folderперед початком

  • -type f - Вказує лише шукати файли

  • -iname "*.wav" - Це спонукає його шукати нечутливі регістри * .wav
  • -ls- Це показує файл, над яким він працює. Інакшевибавити це нічого.
  • -exec ditto {} /destination/folder/{} \; - Чи виконується вся робота з копіювання та створення файлів з одним деревом каталогів.

0

Перейдіть до каталогу:

find . -regex '<regexp_to_get_directories_and_files_you_want>' | xargs -i cp -r --parents {} path/to/destination

Це трохи пряміше і сильніше, якщо ви керуєте регулярними виразами.


-1

Перейдіть до каталогу:

cp '*.css' /path/to/destination

Вам доведеться перейти до кожної папки в каталозі, але це краще, ніж більшість варіантів, які я бачив досі.


Цей метод не є рекурсивним, це означає, що для великих каталогів ви могли це робити досить довго ...
Iain Reid
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.