递归删除具有给定扩展名的所有文件

sas*_*alm 249 rm

我想删除*.o目录及其子目录中的所有文件。但是,我收到一个错误:

sashoalm@aspire:~/.Workspace.OLD$ rm -r *.o
rm: cannot remove `*.o': No such file or directory
Run Code Online (Sandbox Code Playgroud)

另一方面,rm *.o有效,但它不是递归的。

Hau*_*ing 385

这是邪恶的:rm -r不是删除文件,而是删除目录。幸运的是,可能没有目录匹配*.o.

你想要什么是可能的zsh,但不与shbash(bash的新版本可以做到这一点,但只有当您启用了shell选项globstarshopt -s globstar)。通配模式**/*.o不仅限于文件(也许zsh也有排除非文件的技巧)。

但这是为了find

find . -type f -name '*.o' -delete
Run Code Online (Sandbox Code Playgroud)

或(因为我不确定是否-delete是 POSIX)

find . -type f -name '*.o' -exec rm {} +
Run Code Online (Sandbox Code Playgroud)

  • 你能解释一下这种情况下的花括号和加号吗? (10认同)
  • @AubreyRobertson 请参阅“查找”的手册页。`-exec +`(与 `-exec ;` 相反)一次处理多个文件。`{}` 是文件名/路径的占位符(在这两种情况下)。 (6认同)
  • @stpoa 我鼓励您尝试找到我的代码无法按预期工作的示例。 (5认同)
  • 在 macOS 上运行良好 (4认同)

ter*_*don 71

这不是-rswitch 的rm工作原理:

-r, -R, --recursive
          remove directories and their contents recursively
Run Code Online (Sandbox Code Playgroud)

rm没有文件搜索功能,它的-r开关不会使其下降到本地目录并识别与您提供的模式匹配的文件。相反,模式 ( *.o) 由 shell 展开,rm并将下降到并删除名称与该模式匹配的任何目录。如果您有一个名称以 结尾的目录.o,那么您尝试的命令会删除它,但它不会.o在子目录中找到文件。

您需要做的是使用find

find . -name '*.o' -delete
Run Code Online (Sandbox Code Playgroud)

或者,对于非 GNU find

find . -name '*.o' -exec rm -r {} \;
Run Code Online (Sandbox Code Playgroud)

或者,如果您正在使用,bash您可以启用globstar

shopt -s globstar
rm -r -- **/*.o
Run Code Online (Sandbox Code Playgroud)

注意:所有三个选项都将删除名称以 结尾的目录.o,如果这不是您想要的,请使用以下选项之一:

find . -type f -name '*.o' -delete
find . -type f -name '*.o' -exec rm {} \;
rm -- **/*.o
Run Code Online (Sandbox Code Playgroud)