17

我想知道是否rm可以删除目录中的所有文件(但不能删除子文件夹或子文件夹中的文件)?

我知道有些人使用:

rm -f /direcname/*.*

但这假设文件名具有并非全部都具有的扩展名(我希望所有文件 - 带或不带扩展名都被删除)。

4

8 回答 8

35

Although find allows you to delete files using -exec rm {} \; you can use

find /direcname -maxdepth 1 -type f -delete

and it is faster. Using -delete implies the -depth option, which means process directory contents before directory.

于 2012-05-05T08:51:49.610 回答
7
find /direcname -maxdepth 1 -type f -exec rm {} \;

解释:

  • find搜索文件和目录/direcname
  • -maxdepth将其限制为查找直接子级的文件和目录/direcname
  • -type f将搜索限制为文件
  • -exec rm {} \;为每个文件运行命令rm {}(在替换文件路径之后{})。
于 2012-05-05T08:45:27.150 回答
3

我想知道 rm 是否可以删除目录中的所有文件(但不能删除子文件夹或子文件夹中的文件)?

这很容易:

$ rm folder/*

如果没有-r,该rm命令将不会触及子目录或它们包含的文件。这只会删除其中的文件,folder而不是子目录或其文件。

你会看到错误告诉你folder/foo是一个不能被删除的目录,但实际上你没问题。如果您想消除这些消息,只需重定向 STDERR:

$ rm folder/* 2> /dev/null

顺便说一句,rm命令的退出状态可能不为零,因此您无法检查rm错误。如果这很重要,您将不得不循环:

$ for file in *
> do
> [[ -f $file ]] && rm $file
> [[ $? -ne 0 ]] && echo "Error in removing file '$file'"
> done

即使文件名中有空格,这也应该在 BASH 中工作。

于 2014-02-02T22:48:30.490 回答
2

A shell solution (without the non-standard find -maxdepth) would be

for file in .* *; do
   test -f "$file" && rm "$file"
done
于 2012-05-05T08:50:37.150 回答
2

您可以使用

find /direcname -maxdepth 1 -type f -exec rm -f {} \;
于 2012-05-05T08:44:04.700 回答
1

一些 shell,特别是zsh和可能的 bash 版本 4(但不是版本 3),具有执行此操作的语法。

使用 zsh 你可能只需要输入

rm /dir/path/*(.)

如果你想删除任何名称以 foo 开头的文件,递归地在子目录中,你可以这样做

rm /dir/path/**/foo*(.)

在我看来,双星功能(恕我直言更好的交互式完成)足以切换到 zsh 进行交互式 shell。YMMV

括号后缀中的点表示您只希望 zsh shell 扩展文件(而不是符号链接或目录)。

于 2012-05-05T10:00:15.030 回答
1

Unix不是DOS。文件名中没有特殊的“扩展名”字段。点之后的任何字符都只是名称的一部分,称为后缀。可以有多个后缀,例如.tar.gz. shell glob 字符*匹配整个.字符;它忽略了后缀。所以 MS-DOS*.*只是*在 Unix 中。

几乎。*不匹配以.. 按照惯例,用前导点命名的对象是“隐藏的”。ls除非您指定,否则它们都不会出现在其中-a

(这意味着“self”和“parent”的.和目录条目被认为是隐藏的。)..

要匹配隐藏的条目,请使用.*

rm命令不会删除目录(当不使用 递归操作时-r)。试试看rm <directory>。即使目录为空,它也会拒绝。

因此,您从目录中删除所有(非隐藏)文件、管道、设备、套接字和符号链接(但不理会子目录)的方式实际上是:

rm /path/to/directory/*

还要删除以以下开头的隐藏的.

rm /path/to/directory/{*,.*}

这种语法是大括号扩展。大括号扩展不是模式匹配;它只是生成多个参数的简写,在这种情况下:

rm /path/to/directory/* /path/to/directory/.*

这种扩展首先发生,然后发生 globbing 以生成要删除的名称。

请注意,此处发布的各种解决方案存在各种问题:

find /path/to/directory -type f -delete

# -delete is not Unix standard; GNU find extension
# without -maxdepth 1 this will recurse over all files
# -maxdepth is also a GNU extension
# -type f finds only files; so this neglects to delete symlinks, fifos, etc.

GNU find 解决方案的好处是即使要删除的目录条目数量很大,它们也能正常工作:太大而无法在一次调用中传递rm. 另一个好处是内置-delete没有将有趣的路径名传递给外部命令的问题。

目录条目过多问题的可移植解决方法是列出条目ls并通过管道传输到xargs

( cd /path/to/directory ; ls -a | xargs rm -- )

括号表示“在子进程中执行这些命令”;这样cd就忘记了 的效果,这在脚本编写中很有用。ls -a包括隐藏文件。

我们现在包含一个--after rm,表示“这是最后一个选项;其他所有内容都是非选项参数”。这可以保护我们免受名称与选项无法区分的目录条目。如果一个文件被调用-rf并以第一个参数结尾怎么办?然后你有 rm -rf ...哪个会吹掉子目录。

于 2012-05-05T19:42:04.057 回答
1

The easiest way to do this is to use:

rm *

In order to remove directories, you must specify the option -r

rm -r

so your directories and anything contained in them will not be removed by using

rm *

per the man page for rm, its purpose is to remove files, which is why this works

于 2016-06-03T14:42:35.483 回答