Как переместить все файлы в существующие подпапки сюда

8

У меня также есть 50 папок с некоторыми подпапками, всего более 1000 аудиофайлов. Мне нужно удалить все подпапки и поместить все файлы в текущий уровень. Пытался, mv */* ./но это жалобы: список аргументов слишком длинный

Педро Гонсалес
источник

Ответы:

7

Я предполагаю, что ваши аудио файлы расширены .mp3

find <AudioFolderPath> -name '*.mp3' -exec mv -it <YourTargetFolder> {} +

Ноты:

  • Замените .mp3своим расширением аудио файлов

  • Замените <AudioParentFolderPath>родительской папкой, содержащей ваши подпапки.

  • Замените <YourTargetFolder>путь к папке, в которую нужно поместить все файлы.

  • Если файлы буксировки из разных подпапок имеют одинаковые имена, будет перемещен только один.

редактировать: как сказал Костас : « -iПереключатель делает mvинтерактивным, он будет запрашивать перед перезаписью существующих файлов»

Мухаммед
источник
'-t' позволяет вам сначала указать пункт назначения? (поскольку у меня нет этой опции на моем "mv" здесь, я могу только предположить, что, так как вы помещаете сначала папку назначения, а затем список файлов для перемещения туда ... но если нет, это попытается уместить все в последнем имени файла, выдавая предупреждение) tможет быть за "цель"?
Оливье Дюлак
Да, как вы сказали, -tпозвольте сначала указать пункт назначения. со mvстраницы руководства: -t, --target-directory=DIRECTORY move all SOURCE arguments into DIRECTORY
Мухаммед
1
обратите внимание, что это опция GNU mv, и она доступна не на всех устройствах (по крайней мере, в некоторых производственных средах). Я предоставляю более портативное решение, но ваше прекрасно работает для Linux
Оливье Дюлак
да @OlivierDulac, вы правы, спасибо за вашу заметку.
Мухаммед
4
find . -type f -mindepth 2 -exec mv -t ./ {} +

Обратите внимание, что эта команда перезапишет любые файлы с таким же именем. Вы можете использовать это, чтобы получить запрос перед перезаписью:

find . -type f -mindepth 2 -exec mv -it ./ {} +

объяснение

  • -type f : найти только обычные файлы.
  • -mindepth 2 : найти только файлы в подкаталогах.
  • -exec mv -it ./ {}: -execозначает «выполнить эту команду для каждого найденного файла». {}Будут заменены именами файлов. -iПереключатель делает mvинтерактивным, он будет запрашивать перед перезаписью существующих файлов и -tустанавливает целевой каталог ./.
  • +: объедините файлы (в одну строку аргумента) так, чтобы оболочка могла работать с командой, чтобы вызывать команду минимальное время (не один за другим, а один к нескольким).

Что касается дальнейшего удаления пустой папки, вы можете использовать тот же получатель:

find . -type d -empty -delete
Костас
источник
1
-type fвыбирает только простые файлы, исключая символические ссылки, именованные каналы и тому подобное. Для перемещения всех файлов, кроме каталогов, вы можете сделать ! -type d.
Джимми
@jimmij Полагаю, никто не хранит аудио-файлы как именованные каналы или что-то еще. Если вы беспокоитесь о символических ссылках, вы можете использовать -Lпараметр
Costas
1
-iявляется стандартным, -tтолько для GNU (ничего общего с Linux, который является просто ядром в некоторых системах GNU и не-GNU)
Стефан Шазелас
Я согласен с @ StéphaneChazelas: -tне существует в некоторых системах (например, не очень древний AIX)
Оливье Дюлак
@OlivierDulac Практически невозможно найти решение, чтобы удовлетворить всех, поэтому приветствуются разные варианты. Никто не запрещает вам менять строку наfind . -type f -mindepth 2 -exec mv {} ./ \;
Костас
2

Да, это ограничение на совокупный размер аргументов и среды, передаваемых execve()системному вызову при выполнении внешней команды.

С помощью zshвы можете использовать его встроенный mvвместо:

zmodload -F zsh/files +b:zf_mv
zf_mv ./*/* .

Или используйте, zargsчтобы разбить список на управляемые куски:

autoload zargs
zargs -Ifiles ./*/* -- mv files .

С ksh93:

command -x mv ./*/* .

С GNU xargsи GNU mvс printfвстроенной оболочкой (большинство, mkshявляясь заметным исключением):

printf '%s\0' ./*/* | xargs -r0 mv -t .
Стефан Шазелас
источник
Помните, что OP хочет перемещать только файлы, а не каталоги, поэтому вам нужно позаботиться об этом. В zshслучае, если вы можете поставить некоторые глоб-классификаторы , например, (.)или (^/)после последней *.
Джимми
0

Довольно портативное решение может быть:

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

find ./*/ -type f -print | xargs mv -i "{}" ./

Вы можете добавить | egrep "\.au$|\.mp3$|\.ac3$"промежуточный файл, чтобы убедиться, что найденные файлы являются файлами с аудио-расширением (добавьте столько расширений, сколько необходимо, чтобы охватить все типы, я просто предоставил 3 общих)

Оливье Дюлак
источник
В вашем случае нет необходимости звонить findвообще. Достаточно echoилиprintf
Костас
@Costas: ОП упоминает, что существует так много файлов, что «*» не может быть расширен ... Здесь я просто раскрываю имена 50 папок, а остальное обрабатывает xargs
Оливье Дюлак
Но findне решайте проблему, а xargsрешайте.
Костас