Как удалить все подкаталоги из каталога?


51

Этот вопрос является своего рода этапом II к первому вопросу, который я разместил здесь

У меня есть каталог, который содержит множество подкаталогов, ZIP-файлы и другие случайные файлы, не содержащиеся в подкаталоге.

Мне бы хотелось, чтобы скрипт командной строки удалял все подкаталоги из родительского каталога, но оставлял все zip-файлы и свободные файлы, которые не принадлежат никаким подкаталогам. Все подкаталоги имеют контент, поэтому я считаю, что мне нужно принудительно удалить их с помощью команды -f.

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

Я понимаю, что удаление элементов из командной строки требует особой осторожности, но я уже принял все необходимые меры предосторожности для резервного копирования удаленно.

Ответы:


62

В BASH вы можете использовать косую черту (я думаю, она должна работать в любой оболочке POSIX):

rm -R -- */

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

Добавьте эту -fопцию, если вы не хотите получать запрос на подтверждение при удалении файлов, которые нельзя записать.

Обратите внимание, что по умолчанию скрытые каталоги (те, чье имя начинается с .) будут оставлены в покое.

Важное предостережение: расширение */также будет включать символические ссылки, которые в конечном итоге преобразуются в файлы типа directory . И в зависимости от rmреализации, rm -R -- thelink/либо просто удалите символическую ссылку, либо (в большинстве из них) рекурсивно удалите содержимое связанного каталога, но не сам каталог или символическую ссылку.

В этом случае zshлучше использовать квалификатор glob для выбора только файлов типа directory:

rm -R -- *(/) # or *(D/) to include hidden ones

или же:

rm -R -- *(-/)

включить символические ссылки на каталоги (но, поскольку на этот раз у расширения нет завершающих /s, только символическая ссылка удаляется со всеми rmреализациями).

С помощью bashAT & T ksh, yashили zshвы можете сделать:

set -- */
rm -R -- "${@%/}"

снять след /.


Красивый! Это работает отлично. Я не понимал, что это было так легко сделать. Не могли бы вы остановиться на -r против -R и что эти команды делают? Большое спасибо.
Евстер

-r, -R, --recursiveЯвляются синонимами означает «удалить каталоги и их содержимое рекурсивно».
Петер

Вы можете объяснить, что - и * / делать?
амфибия

6
Вы также можете сказать rm -R ./*/- это также позволяет избежать проблем с именами дефисов.
мая 2013 года

1
Только будьте осторожны, чтобы не изменить порядок * и /. rm -R - / * делает что-то совершенно другое, чего вы, возможно, не захотите: |
ChrisOdney

13

В дополнение к подстановочному способу вы также можете использовать find(по крайней мере, GNU find) для этого:

find -mindepth 1 -maxdepth 1 -type d -print0 | xargs -0 rm -R

Как и в случае с другими findстроками, вы можете запустить first part ( find -mindepth 1 -maxdepth 1 -type d), чтобы увидеть список каталогов, которые будут удалены.

Более безопасный вариант - сделать что-то вроде этого:

find -mindepth 1 -maxdepth 1 -type d -print0 | xargs -0 mv -i -t ../to-rm
# or
mv -i -t ../to-rm */
# or
mv -i */ ../to-rm

любой из которых переместит весь материал ../to-rmвместо того, чтобы удалить его. Вы можете проверить, что он сделал то, что вы хотели, им rm -Rfэтот каталог на досуге.


+1 для «CLI-Мусорное ведро» to-rmи findкоторый хорошо обрабатывает каталоги , начинающиеся с точки (в дополнение к любым другим громоздких отводящей). :)
Петер

Спасибо за чаевые. Мне нравится идея перемещения в отдельный каталог перед удалением. Я работаю через терминал в Mac OS X и считаю, что мне нужно установить какой-то пакет GNU для использования команд -mindepth и -maxdepth, правильно?
Евстер

@Evster не уверен, что Mac OS X find поддерживает их. Я думаю, Fink (это все еще рядом?) Может установить находку, которая делает. Или вы можете опустить их, а затем отфильтровать список созданных файлов с помощью grep. Определенно используйте опцию mv вместо rm.
Дероберт

4

Возможно, вы захотите создать сценарий для некоторых из этих предложений, особенно rm -R -- */, и сохранить его в папке / usr / local / bin; или создайте aliasфайл ~ / .bashrc. Так как это так легко опечатка команды и сломать систему - хотя бы одну буквы и / или порядка букв могут привести к катастрофическим последствиям - это служил бы несколько более надежным решением , чем того , чтобы вводить различные опции и аргументы каждый раз, когда вы хотите выполнить эту задачу.

Кроме того, вы можете захотеть включить опцию -i or --interactive=onceили -I or --interactive=alwaysв ваш скрипт / команду, которая будет служить другим инструментом, чтобы избежать непреднамеренного удаления.

Кроме того, что-то вроде Дероберта было бы лучше; просто скопируйте / вставьте скрипт в файл / терминал-редактор и настройте его в соответствии с вашими потребностями, и файлы / каталоги будут перемещены в один каталог (содержимое которого вы можете проверить / проверить), который вы можете просто удалить с помощью выдача rm -rfкоманды.

Другой вариант - использовать GUI-приложение, такое как ваш файловый менеджер, и просто выбрать все соответствующие файлы / папки, которые вы хотите удалить. Проверьте справочные страницы вашего дистрибутива, если у вас нет прав.

Наконец, если папки пусты - по существу, простые имена файлов - вы можете использовать rmdirкоманду для их удаления. Это не работает для всего, что вы, возможно, захотите удалить, но пригодится в те моменты, когда вы захотите провести «уборку дома». ** Вы можете попробовать -p --ignore-fail-on-non-emptyопцию, которая позволит вам удалить определенные подкаталоги, а также их пустые «родители» - каталоги, в которых они находятся.


Это действительно хорошая идея по созданию отдельного скрипта, который я могу вызвать для этой команды. Можете ли вы объяснить, что именно делают опции -i и -I? Спасибо!
Евстер

-Я опция предложит вам один раз после того, как вы нажмете «Enter», чтобы подтвердить, что вы хотите удалить это (когда выбрано более 3 файлов / папок); тогда как опция -i выдаст подсказку для каждого файла, после чего вы можете просто подтвердить, нажав «y» и «Enter» - что угодно, кроме утвердительного ответа, этот конкретный файл будет пропущен в процессе удаления.
ILMostro_7

1

Сначала вам нужно вывести список каталогов, а затем удалить их, не мешая обычным файлам, ls -d * /, перечисляет только подкаталоги, а передача его с помощью rm удаляет каталоги и их содержимое, сохраняя свободные файлы нетронутыми.

Эта команда должна сделать работу,

ls -d  */ | xargs rm -rf

1
Какая будет польза rm -rf -- */? printf '%s\0' */ | xargs -r0 rm -rf --поможет (в оболочках, где printfвстроен, а не ls), чтобы обойти список arg слишком большие ошибки, но ls -d */ | xargs rm -rfне добавляет ничего AFAICT, кроме дополнительных проблем.
Стефан

1
@AnthonyGeoghegan, да, например, если бы существовал каталог с именем " .."(пробел ..), он удалил бы содержимое родительского каталога с некоторыми lsреализациями. И это не только пробелы, но и другие пустые символы, новая строка, одинарные кавычки, двойные кавычки, обратная косая черта и имена файлов, начинающиеся с -.
Стефан

2
@ Анкит, ты можешь начать с mywiki.wooledge.org/ParsingLs
Стефан

1
Когда вы полностью поймете предложение @ StéphaneChazelas об использовании printfдля создания списка, в котором каждое имя заканчивается нулевым символом, чтобы его можно было обработать с xargsпомощью этой -0опции, я бы посоветовал вам отредактировать свой ответ, чтобы обновить его с его вариацией. Я был бы совершенно уверен, что он был бы рад, если бы вы использовали его фрагмент кода, если вы понимаете его и узнали, как он защищает от нежелательного поведения, вызванного определенными именами файлов, которые могут потенциально существовать.
Энтони Дж. - правосудие для Моники

1
Использование xargsимеет одно преимущество перед принятым ответом (оно работает, когда в текущем каталоге очень большое количество файлов / каталогов), поэтому есть возможность отредактировать его до полезного ответа. Лично я считаю, что ответы на вопросы по Stack Exchange являются хорошим опытом обучения, особенно когда я получаю полезную обратную связь от других пользователей.
Энтони Дж. - правосудие для Моники

-1

rm -rf <directory name>, Оно работает. Просто ввод текста rm <directory name>приводит к количеству подвопросов, в которых каждый из подкаталогов должен быть удален вручную. Но rm -rfпомогает в удалении всего каталога вместе с его подкаталогами.


5
ОП попросил сохранить содержимое текущего каталога.
Стивен Раух
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.