Перемістіть усі файли з певним розширенням з декількох підкаталогів в один каталог


43

У мене є маса файлів .zip у кількох каталогах:

Fol1/Fol2
Fol3
Fol4/Fol5

Як я можу перенести їх у загальну базову папку?


Ви хочете зберегти структуру каталогу? Ви хочете перемістити каталоги чи просто поштові файли?
Йорданм

Я просто хочу перемістити поштові файли. Мені зовсім не цікаво каталогів - їх можна залишити в спокої або видалити.
InquilineKea

Відповіді:


55

Перейдіть до каталогу вершин дерева, що містить zip-файли ( cd …), та запустіть

mv **/*.zip /path/to/single/target/directory

Це працює з коробки в zsh. Якщо ваша оболонка є баш, вам потрібно запустити shopt -s globstarспочатку (ви можете та маєте поставити цю команду у свою ~/.bashrc). Якщо ваша оболонка є ksh, вам потрібно запустити set -o globstarспочатку (помістіть її у свій ~/.kshrc).

Як варіант, використання find, яке працює скрізь без спеціальної підготовки, але є складнішим:

find . -name '*.zip' -exec mv {} /path/to/single/target/directory \;

Якщо після цього потрібно видалити порожні каталоги, в zsh:

rmdir **/*(/^Fod)

В bash або ksh:

rmdir **/*/

і повторюйте, доки є порожні каталоги, які потрібно видалити. Як варіант, у будь-якій оболонці

find . -depth -type d -empty -exec rmdir {} \;

Перша findкоманда вище працювала в bash, але її довелося змінити на find . -nameetc, щоб змусити її працювати.
JeffThompson

1
@Jeff .неявний для пошуку GNU, але не для інших, я додав це явно.
Жил "ТАК - перестань бути злим"

13

Якщо ви хочете лише переміщувати .zipфайли, ви можете зробити щось подібне

mkdir ./zipfiles
find . -name "*.zip" -exec mv "{}" ./zipfiles \;

3

Якщо ви використовуєте bash версії 4 або вище або zsh, ви також можете використовувати рекурсивний глобулінг:

mv **/*.zip /path/to/move/zip/files/to

Це перемістить ТІЛЬКИ файли, а не їх відносні шляхи, тому можуть виникнути зіткнення.


що ви маєте на увазі під відносними шляхами?
Кунок

2

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

find . -name *.flac -exec mv '{}' "./flac/" ";"
  • Запустіть цю команду в головному каталозі, який містить підкаталоги з файлами, які ви хочете перемістити.
  • Де ви можете змінити *.flacбудь-що, як *.zipу вашому випадку. Або *.docпросто будь-яке розширення працює.
  • і mvце команда переміщення файлів, або ви можете використовувати cpдля копіювання даних замість переміщення.
  • ./flac/- це каталог призначення, до якого я хочу перемістити всі файли FLAC. Ви також можете дати йому повний шлях, як/home/myid/flac/

Повний приклад. (В даному випадку, є багато підкаталогів з ім'ям музики художника в /home/myid/Music/і потім FLAC файли все більш різний рівень підкаталогів. Так як мені не потрібен художник папка , але хоче мати все FLAC файлів в один каталог на/home/myid/Music/flac/

cd /home/myid/Music
mkdir flac
find . -name *.flac -exec mv '{}' "./flac/" ";"
cd flac
ls

Тоді він покаже всі файли FLAC.


що робить ;?
Франческо Бой

@FrancescoBoi не забудьте почекати, поки команда bash у тому ж рядку закінчить свою роботу. а потім переходимо до наступного рядка команд bash. Це корисно для команд, що містять такі сценарії, як .pl або python, тому що bash просто запустить його, а потім перейде до наступного рядка, так що для безпеки я використовую; після команд, які потребують часу або сценарію, на випадок, коли баш пропустить його.
Seandex

0

Як баш-хак, ви можете використовувати силу tar:

(cd origin/;find . -exec file --mime-type "{}" \;|grep "application/zip"|cut -d ':' -f 1|xargs tar cf -)|(cd target/; tar xf -) && rm -fr origin/

Перевага полягає в тому, що він не залежить від розширень файлів, оскільки він використовує fileкоманду для вибору файлів для переміщення і зберігає структуру каталогів, але він не працює з шляхами, що містять пробіли.

Останнє rmє лише для того, щоб видалити оригінальні файли (оскільки @InquilineKea каже, що він не хвилює оригінальну папку в коментарі).

Звичайно, це особливо підходить, якщо походження / та цілі / папки знаходяться на різних дисках. В іншому випадку інші запропоновані рішення є більш ефективними (навіть якщо вони покладаються на конвенції про іменування, а не на fileзміст).


0

Якщо припустити, що у вас є версії GNU find and mv, наступні будуть ефективнішими, ніж існуючі відповіді на основі знахідки:

find . -name '*.zip' -exec mv --target-directory='/path/to/outputdir' '{}' +

Використання a +в кінці find -exec означає, що список файлів буде переданий команді mv, а не виконувати одну команду mv на знайдений файл. Однак обмеженням цього є те, що ви можете розміщувати '{}' лише в кінці команди, що вимагає використання опції mv --target-каталог, і наскільки я знаю, це GNU-ism.

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