Как я могу рекурсивно переместить все файлы в подкаталогах в один каталог?

10

Я пытаюсь собрать все файлы в текущем каталоге и все подкаталоги в один каталог. Я пытаюсь что-то вроде следующего

find -type f -exec mv {} collection/{} \; 

вышеупомянутая команда не будет работать, потому что вторая {}дает полный путь, как я могу собрать все файлы?

Кролик кролик
источник

Ответы:

14

Удалить {}из mv, mvпримет его в качестве целевого каталога, игнорируя любые родительские каталоги:

find -type f -exec mv {} collection/ \;
Lekensteyn
источник
о, это не пришло мне в голову. спасибо :)
Кролик Банни
Как я сказал в своем ответе на вопрос, это потенциально плохая идея. Возможно, использование аргумента -maxdepth 1поможет.
loevborg
Если подумать, похоже, я неправильно прочитал ваш вопрос :) Извините.
loevborg
@loevborg: теперь я добавил «рекурсивно» к названию. Если все еще есть путаница, пожалуйста, отредактируйте и улучшите ее :)
Лекенштейн
1
более быстрый вариант этого ответаfind -type f -print0|xargs -0r mv -it colection/
Hildred
5

Вместо использования find(которое хорошо работает) вы также можете использовать оболочку для этой цели.

Скажем, вы хотите, чтобы все файлы от $ PWD до $ DEST. Естественная попытка будет:

mv $PWD/* $DEST

Как это работает? Выражение «$ PWD / *» распространяется на имена всех файлов в этом каталоге. Эта функция оболочки называется "globbing". Последний аргумент mv- это каталог назначения. Если у вас очень много файлов, это не сработает, потому что длина командной строки ограничена.

Но у решения есть проблема, что он пропускает точечные файлы - или «скрытые» файлы, файлы и каталоги, чье имя начинается с «.». Чтобы решить эту проблему, вы должны указать своей оболочке включить файлы точек при глобализации. Для этого используйте

shopt -s dotglob

при использовании bash(и вы, вероятно, используете, bashесли вы не изменили по умолчанию). В этой оболочке приведенная выше команда будет работать и для точечных файлов.

Кроме того, у zshвас есть возможность выбрать это в каждом конкретном случае. Для этого нужно поставить

setopt extendedglob

в вашем .zshrc. Тогда вы можете использовать

mv $PWD/*(D) $DEST

переместить все файлы, включая точечные файлы. («D» приводит к временному включению опции «GLOB_DOTS»).

Теперь первоначальный вопрос состоял в том, чтобы переместить все обычные файлы (не каталоги) из всех подкаталогов и их подкаталогов в один каталог. Это может быть достигнуто с помощью zsh:

mv $PWD/**/*(D.)

Здесь выражение **/*заставляет глобер рекурсивно спускаться в подкаталоги. В Dсредства «также выбрать точечные файлы, а .значит„выбрать только обычные файлы, а не каталоги“.

loevborg
источник
ну, я тоже хотел пройтись по всем подкаталогам, но, благодаря любой информации, полезной, слишком часто сталкивался с этой ситуацией :)
Кролик Банни
На самом деле, поиск не является излишним, глобализация выберет все совпадения, не только файлы, но и каталоги. Если вы беспокоиться о производительности, вы можете также использовать что - то вроде: find -type f -exec mv -t collection/ {} +. Обратитесь к странице руководства о том, как это работает.
Лекенштейн
Лекенштейн, ты прав. Я обновил ответ теперь, когда понял вопрос.
loevborg
2
Замечательный ответ, очень плохо, что это не особенно относится к вопросу :).
crazy2be