如何从目录中删除所有子目录?


51

这个问题是我在此处发布的第一个问题的第二阶段

我有一个目录,其中包含一堆子目录,.zip文件以及未包含在子目录中的其他随机文件。

我想使用命令行脚本从父目录中删除所有子目录,但保留所有不属于任何子目录的zip文件和松散文件。所有子目录都有内容,因此我相信我需要使用-f命令强制将其删除。

因此,基本上,在父目录(或当前目录)中查找的命令会删除其中的所有文件夹,但会保留不是文件夹或包含在文件夹中的所有其他内容和文件。

我知道从命令行删除项目需要特别注意,但是我已经采取了所有必要的预防措施进行远程备份。

Answers:


61

在BASH中,您可以使用斜杠(我认为它可以在任何POSIX shell中使用):

rm -R -- */

请注意,--该选项将选项与参数分开,并允许它们删除以连字符开头的条目-否则,在由Shell扩展后,条目名称将被解释为选项rm(许多其他命令行实用程序也是如此)。

-f如果不想在删除不可写文件时提示您确认,请添加选项。

请注意,默认情况下,隐藏目录(名称以开头的目录.)将被保留。

一个重要的警告:的扩展*/还将包括符号链接,这些符号链接最终将解析为directory类型的文件。并且根据rm实现方式,rm -R -- thelink/将只是删除符号链接,或者(在大多数情况下)以递归方式删除链接目录的内容,而不是该目录本身或符号链接。

如果使用zsh,则更好的方法是使用glob限定符来选择目录类型的文件:

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

要么:

rm -R -- *(-/)

包括指向目录的符号链接(但是因为这次扩展没有尾随/s,所以只有所有rm实现中都删除了符号链接)。

随着bash,AT&T kshyash或者zsh你可以这样做:

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

剥离尾随/


美丽!这很完美。我没有意识到这是如此容易。您介意-r和-R以及这些命令的作用吗?非常感谢。
Evster

-r-R--recursive是同义词,意思是“删除目录及其内容递归”。
彼得

您能解释一下-和* /做什么吗?
两栖游戏2013年

6
您也可以说rm -R ./*/-还可避免连字符名称出现问题。
l0b0

1
请注意不要更改*和/的顺序。rm -R-/ *做的事情与您可能不想发生的完全不同:|
ChrisOdney '17

13

除了通配符方式之外,您还可以使用find(至少是GNU find)来执行此操作:

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

与其他find行一样,您可以运行第一部分(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-rmfind它可以很好地处理以点开头的目录(除其他麻烦的转义外)。:)
彼得

谢谢你的提示。我喜欢删除之前移到单独目录的想法。我正在Mac OS X上通过Terminal进行工作,我相信我需要安装某种GNU软件包才能使用-mindepth和-maxdepth命令,对吗?
Evster

@Evster不确定Mac OS X查找是否支持那些。我猜芬克(那还在吗?)可以安装一个可以找到的东西。或者,您可以忽略它们,然后使用grep过滤生成的文件列表。绝对在上面使用mv选项,而不是rm。
derobert 2013年

4

您可能想为其中的一些建议创建脚本,尤其是rm -R -- */,并将其保存在/ usr / local / bin文件夹中。或alias在〜/ .bashrc文件中创建一个。因为它是那么容易敲错了命令,打破你的系统-即使单个字母和/或字母可能导致灾难性的后果的顺序-这将成为一个较为强大的解决方案不必键入不同的选项和参数每次您想完成此任务。

另外,您可能希望在脚本/命令中包含-i or --interactive=once-I or --interactive=always选项,这将用作避免意外删除的另一种工具。

此外,像derobert建议的那样最好。只需将脚本复制/粘贴到文件/终端编辑器中,并根据您的特定需求进行调整,文件/目录将被移至一个目录(您可以检查/验证其内容),您可以通过以下方式简单地删除该目录发出rm -rf命令。

另一种选择是使用GUI应用程序(例如文件管理器),然后仅选择要删除的所有适用文件/文件夹。如果您没有权限,请查看发行版的手册页。

最后,如果文件夹为空(本质上是简单的文件名),则可以使用rmdir命令将其删除。它不适用于您可能要删除的所有内容,但有时在您需要进行“房屋清洁”时会派上用场。**您可能想尝试该-p --ignore-fail-on-non-empty选项,该选项将允许您删除某些子目录及其空的“父级”(它们所在的目录)。


这是创建一个我可以调用此命令的单独脚本的好主意。您能解释一下-i和-I选项的作用吗?谢谢!
Evster 2013年

-I选项将在您按“ Enter”键后提示您一次,以确认您要删除此文件(当“选择”的文件/文件夹超过3个时);而-i选项将为每个文件发出提示,您可以通过点击“ y”和“ Enter”简单地进行确认-除肯定响应外,任何其他操作都会导致该特定文件在删除过程中被跳过。
ILMostro_13年

1

首先,您需要列出目录,然后将其删除,而又不妨碍普通文件ls -d * /,仅列出子目录,并用rm对其进行管道删除将删除目录和内容,从而使松散的文件保持完整。

这个命令应该做的

ls -d  */ | xargs rm -rf

1
有什么好处rm -rf -- */呢?printf '%s\0' */ | xargs -r0 rm -rf --将有助于(在shell printf内置而不是shell中ls)解决arg列表太大的错误,但ls -d */ | xargs rm -rf除了其他问题外,不会添加任何AFAICT。
斯特凡Chazelas

1
@AnthonyGeoghegan,是的,例如,如果有一个名为" .."(space ..)的目录,它将通过某些ls实现删除父目录的内容。它不仅是空格,还包括其他空白字符,换行符,单引号,双引号,反斜杠和以-。开头的文件名。
斯特凡Chazelas

2
@Ankit,您可以用开始 mywiki.wooledge.org/ParsingLs
斯特凡Chazelas

1
当您完全理解@StéphaneChazelas的printf用于生成列表的建议时,其中每个名称都以空字符结尾,以便可以xargs使用-0选项处理该名称,我建议您编辑答案以使用其变体对其进行更新。我非常有信心,如果您了解他的代码片段,并且了解到它如何防止可能由某些文件名引起的不良行为,他将很高兴您使用他的代码片段。
安东尼G-莫妮卡的正义

1
使用xargs确实比接受的答案有一个优势(当当前目录中有大量文件/目录时,它可以工作),因此可以将其编辑为有用的答案。就个人而言,我发现回答Stack Exchange问题是一种很好的学习体验,尤其是当我得到其他用户的有用反馈时。
安东尼G-莫妮卡的正义

-1

rm -rf <directory name>。有用。仅仅键入rm <directory name>会导致许多子问题,其中必须手动删除每个子目录。但是,rm -rf有助于立即删除整个目录及其子目录。


5
OP要求保留当前目录的内容。
Stephen Rauch
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.