为什么 `find -type d -exec rmdir {} \;` 命令会产生“没有这样的文件或目录消息”

为什么 `find -type d -exec rmdir {} \;` 命令会产生“没有这样的文件或目录消息”

出于测试目的,我创建了以下目录。

user@linux:~$ mkdir dir0{1..3}

user@linux:~$ ls -l
total 12K
drwxr-xr-x 2 user user 4.0K Mei  31 10:45 dir01
drwxr-xr-x 2 user user 4.0K Mei  31 10:45 dir02
drwxr-xr-x 2 user user 4.0K Mei  31 10:45 dir03
user@linux:~$ 

然后,我删除了它find -exec

user@linux:~$ find -type d -exec rmdir {} \;
rmdir: failed to remove '.': Invalid argument
find: ‘./dir02’: No such file or directory
find: ‘./dir01’: No such file or directory
find: ‘./dir03’: No such file or directory
user@linux:~$ 

目录已删除,我已验证。

user@linux:~$ ls -l
total 0
user@linux:~$ 

我的问题是:

1)我不明白为什么会有这些消息。知道为什么吗?

rmdir: failed to remove '.': Invalid argument
find: ‘./dir02’: No such file or directory

我没有看到这种错误rmdir

user@linux:~$ mkdir dir0{1..3}
user@linux:~$ 

user@linux:~$ ls -l
total 12K
drwxr-xr-x 2 user user 4.0K Mei  31 22:58 dir01
drwxr-xr-x 2 user user 4.0K Mei  31 22:58 dir02
drwxr-xr-x 2 user user 4.0K Mei  31 22:58 dir03
user@linux:~$ 

user@linux:~$ rmdir *
user@linux:~$ 

user@linux:~$ ls -l
total 0
user@linux:~$ 

2)是否可以删除这些消息?

答案1

您会收到“没有这样的文件或目录”错误,find因为find正在尝试输入刚刚删除的目录。默认情况下,它会将其操作应用于当前访问的目录中的所有匹配内容,然后再继续进入子目录。

添加到make-depth的调用中,对其搜索路径进行深度优先搜索,这反过来意味着,如果您在目录上执行,它将已经访问过该目录,并且不会尝试再次访问该目录。findfindrmdir

由于这个原因(在has的实现中),该-depth选项是隐含的。-deletefind-delete

find . -depth -type d -exec rmdir {} \;

-depth是该实用程序的标准选项find

请注意,rmdir仅适用于空目录。如果您有很多非空目录,上面的命令会产生很多错误消息。

相反,如果您find支持它,请使用-empty

find . -type d -empty -delete

这将删除空目录。

与 afind没有非标准-delete-emtpy

find . -depth -type d -exec sh -c '
    for dirpath do
        set -- "$dirpath"/*
        [ ! -e "$1" ] && rmdir "$dirpath"
    done' sh {} +

这将测试找到的目录是否为空,如果是,则将其删除。

这是一段很长的代码,以避免由于目录非空而看到一些错误消息,但任何错误消息希望生成的内容会更有趣,因为它们可能是“权限被拒绝”错误。将错误重定向到顶部的/dev/null第一个命令中会隐藏此类错误。find

答案2

大概发生的情况是,通过-exec ... \;构造, find 逐步完成其工作:

  • 遍历目录树,查找匹配的条目-type d,以及
  • rmdir一旦发现此类条目,就立即运行。

这意味着,在您的示例中, find 将查看dir01,将其作为稍后输入的目录记住,然后rmdir在其上运行,然后,当尝试递归到 时dir01,会失败,因为它不再存在。

在这种情况下运行 with应该会有所帮助:将发出-exec rmdir {} +单个调用。rmdir dir01 dir02 dir03这消除了最后三个错误消息。

错误信息.是因为,嗯.,当前目录确实是一个目录,但不是一个rmdir可以删除的目录,因为它不为空。使用-min-depth停止考虑它,发出命令:

find -mindepth 1 -type d -exec rmdir {} +

这并不完美;嵌套目录或大量匹配目录仍然可能导致打印错误消息,但这应该适用于问题的简单情况。

相关内容