find exec rm:没有这样的文件或目录

PMo*_*bed 5 linux shell

为什么在下面的示例中“没有这样的文件或目录”?有一些解决方法可以避免出现此错误,问题是为什么在这个确切的示例中会产生错误。

cd /tmp
mkdir -p TOP1/AB/AC/AD/AE/AF
mkdir -p TOP2/AB/AC/AD/AE/AF

find . -iname 'A*' -exec rm -rvf {} \;
removed directory: `./TOP1/AB/AC/AD/AE/AF'
removed directory: `./TOP1/AB/AC/AD/AE'
removed directory: `./TOP1/AB/AC/AD'
removed directory: `./TOP1/AB/AC'
removed directory: `./TOP1/AB'
find: `./TOP1/AB': No such file or directory
removed directory: `./TOP2/AB/AC/AD/AE/AF'
removed directory: `./TOP2/AB/AC/AD/AE'
removed directory: `./TOP2/AB/AC/AD'
removed directory: `./TOP2/AB/AC'
removed directory: `./TOP2/AB'
find: `./TOP2/AB': No such file or directory
Run Code Online (Sandbox Code Playgroud)

使用-depth或\+或-delete修复此问题:

find .        -iname 'A*' -exec rm -rvf {} \+
find . -depth -iname 'A*' -exec rm -rvf {} \;
find . -iname 'A*' -delete
Run Code Online (Sandbox Code Playgroud)

Ken*_*ler 10

我认为答案就在手册页本身中: https: //linux.die.net/man/1/find

另请参阅\;vs +:在 find 中使用分号 (;) 与加号 (+) 和 exec

为了更好地了解整个过程,您可以打印文件而不是删除它们。以TOP1文件夹为例:

find . -iname 'A*' -exec echo "{}" \;
Run Code Online (Sandbox Code Playgroud)

输出:

./TOP1/AB
./TOP1/AB/AC
./TOP1/AB/AC/AD
./TOP1/AB/AC/AD/AE
./TOP1/AB/AC/AD/AE/AF
Run Code Online (Sandbox Code Playgroud)

作用\;是:对当前目录中或当前目录下的每个文件运行 file。 这里的顺序很重要,即首先处理父文件夹,然后递归遍历其子文件夹。

另一方面,这是如何rm -frv工作的:

rm -frv ./TOP1
Run Code Online (Sandbox Code Playgroud)

输出:

removed directory './TOP1/AB/AC/AD/AE/AF'
removed directory './TOP1/AB/AC/AD/AE'
removed directory './TOP1/AB/AC/AD'
removed directory './TOP1/AB/AC'
removed directory './TOP1/AB'
removed directory './TOP1'
Run Code Online (Sandbox Code Playgroud)

所以rm -fr实际上与 相反find,这是问题的主要原因:

find首先\;从父文件夹开始TOP1,其中的文件夹TOP1及其内容将被完全删除-exec rm -rvf {} \;。在下一轮中find,然后将尝试处理下面的下一个子文件夹,显然它首先检查(通过stat ./TOP1),基本文件夹是否仍然存在,然后才更深一层。但由于./TOP1在第一轮中已经被删除,因此stat ./TOP1会失败,因此会出现错误消息。

使用其他可用参数,您find显然可以更改默认行为:

  • -depth:在(父)目录本身之前处理每个目录的内容。-delete 操作还意味着 -deep。(即从底部到顶部移动 - 就像这样rm -fr做一样!)
  • -delete:使用-delete会自动打开该-depth选项
  • 使用+:该-exec rm -rvf {} +部分仅执行一次,例如-exec rm -rvf {} +:
rm -frv ./TOP1/AB ./TOP1/AB/AC ./TOP1/AB/AC/AD ./TOP1/AB/AC/AD/AE ./TOP1/AB/AC/AD/AE/AF
Run Code Online (Sandbox Code Playgroud)

最后但并非最不重要的一点是:当rm与参数一起使用时-fr,它变得非常“宽容”,因此不会抛出错误。它将尝试强制并递归地删除传递给它的所有内容;而且,如果它遇到不存在的文件/目录,它也不会抱怨。