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

43

У меня есть несколько файлов .zip в нескольких каталогах:

Fol1/Fol2
Fol3
Fol4/Fol5

Как бы я переместить их все в общую базовую папку?

InquilineKea
источник
Вы хотите сохранить структуру каталогов? Вы хотите переместить каталоги или просто zip-файлы?
Иордания
Я просто хочу переместить почтовые файлы. Меня не волнует каталоги - их можно оставить в покое или удалить.
InquilineKea

Ответы:

55

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

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

Это работает из коробки в Zsh. Если ваша оболочка - bash, вам нужно 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.
ДжеффТомпсон
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.

Seandex
источник
что делает ;?
Франческо Бой
@FrancescoBoi обязательно дождется, пока команда bash в той же строке завершит свою работу. а затем перейти к следующей строке команд bash. Это полезно для команд, которые содержат сценарии, такие как .pl или python, потому что bash просто запустит его и затем перейдет на следующую строку, поэтому, чтобы быть в безопасности, я использую; после команд, которые требуют времени или сценария, в случае, если bash пропустит его.
Seandex
0

Как взломщик bash, вы можете использовать силу 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 говорит, что ему нет дела до оригинальной папки в комментарии).

Конечно, это особенно подходит, если папки origin и target находятся на разных дисках. В противном случае другие предложенные решения являются более эффективными (даже если они основаны на соглашениях об именах, а не на fileконтенте).

Джакомо Тесио
источник
0

Предполагая, что у вас есть GNU-версии find и mv, следующее будет более эффективным, чем существующие ответы на основе find:

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

Использование +в конце find -exec означает, что список файлов будет передан команде mv, вместо того, чтобы выполнять одну команду mv на каждый найденный файл. Однако ограничением этого является то, что вы можете поместить только «{}» в конце команды, что требует использования опции mv --target-directory, и, насколько я знаю, это GNU-изм.

evilsoup
источник