繁体   English   中英

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

[英]find exec rm: No such file or directory

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

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

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

find .        -iname 'A*' -exec rm -rvf {} \+
find . -depth -iname 'A*' -exec rm -rvf {} \;
find . -iname 'A*' -delete

这是find的实现细节。 您将在其源代码中找到问题的最终答案。

在 Linux 上,了解幕后发生的事情的另一种方法是strace 我从下面的 strace 中准备了一些有趣的 output。 您可以通过 find 调用(使用和不-depth )查看openat系统调用问题的顺序:

mkdir -pv TOP{1,2}/AB/AC/AD/AE/AF && strace -o foo find . -depth -iname 'A*' -exec rm -rvf {} \; ; grep openat foo
mkdir: created directory 'TOP1/AB'
mkdir: created directory 'TOP1/AB/AC'
mkdir: created directory 'TOP1/AB/AC/AD'
mkdir: created directory 'TOP1/AB/AC/AD/AE'
mkdir: created directory 'TOP1/AB/AC/AD/AE/AF'
mkdir: created directory 'TOP2/AB'
mkdir: created directory 'TOP2/AB/AC'
mkdir: created directory 'TOP2/AB/AC/AD'
mkdir: created directory 'TOP2/AB/AC/AD/AE'
mkdir: created directory 'TOP2/AB/AC/AD/AE/AF'
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 './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'
5:openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
9:openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
20:openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libm.so.6", O_RDONLY|O_CLOEXEC) = 3
28:openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
44:openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libpcre2-8.so.0", O_RDONLY|O_CLOEXEC) = 3
52:openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
60:openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
93:openat(AT_FDCWD, "/proc/filesystems", O_RDONLY|O_CLOEXEC) = 3
99:openat(AT_FDCWD, ".", O_RDONLY|O_CLOEXEC) = 3
102:openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 4
106:openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache", O_RDONLY) = 4
114:openat(AT_FDCWD, ".", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 4
125:openat(5, "TOP1", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 6
137:openat(7, "AB", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 6
149:openat(8, "AC", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 6
161:openat(9, "AD", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 6
173:openat(10, "AE", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 6
186:openat(11, "AF", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 5
223:openat(8, "..", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 5
231:openat(5, "..", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 6
237:openat(6, "TOP2", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 5
249:openat(7, "AB", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 5
261:openat(8, "AC", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 5
273:openat(9, "AD", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 5
285:openat(10, "AE", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 5
298:openat(11, "AF", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 5
332:openat(8, "..", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 5
340:openat(5, "..", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 6




mkdir -pv TOP{1,2}/AB/AC/AD/AE/AF && strace -o foo find . -iname 'A*' -exec rm -rvf {} \; ; grep openat foo
mkdir: created directory 'TOP1/AB'
mkdir: created directory 'TOP1/AB/AC'
mkdir: created directory 'TOP1/AB/AC/AD'
mkdir: created directory 'TOP1/AB/AC/AD/AE'
mkdir: created directory 'TOP1/AB/AC/AD/AE/AF'
mkdir: created directory 'TOP2/AB'
mkdir: created directory 'TOP2/AB/AC'
mkdir: created directory 'TOP2/AB/AC/AD'
mkdir: created directory 'TOP2/AB/AC/AD/AE'
mkdir: created directory 'TOP2/AB/AC/AD/AE/AF'
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
5:openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
9:openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
20:openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libm.so.6", O_RDONLY|O_CLOEXEC) = 3
28:openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
44:openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libpcre2-8.so.0", O_RDONLY|O_CLOEXEC) = 3
52:openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
60:openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
93:openat(AT_FDCWD, "/proc/filesystems", O_RDONLY|O_CLOEXEC) = 3
99:openat(AT_FDCWD, ".", O_RDONLY|O_CLOEXEC) = 3
102:openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 4
106:openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache", O_RDONLY) = 4
114:openat(AT_FDCWD, ".", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 4
125:openat(5, "TOP1", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 6
142:openat(7, "AB", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = -1 ENOENT (No such file or directory)
143:openat(AT_FDCWD, "/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 6
148:openat(AT_FDCWD, "/usr/share/locale/en_US/LC_MESSAGES/findutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
149:openat(AT_FDCWD, "/usr/share/locale/en/LC_MESSAGES/findutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
150:openat(AT_FDCWD, "/usr/share/locale-langpack/en_US/LC_MESSAGES/findutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
151:openat(AT_FDCWD, "/usr/share/locale-langpack/en/LC_MESSAGES/findutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
154:openat(AT_FDCWD, "/usr/share/locale/en_US/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
155:openat(AT_FDCWD, "/usr/share/locale/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
156:openat(AT_FDCWD, "/usr/share/locale-langpack/en_US/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
157:openat(AT_FDCWD, "/usr/share/locale-langpack/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
164:openat(5, "TOP2", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 6
179:openat(7, "AB", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = -1 ENOENT (No such file or directory)

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

另见\; vs +在 find 中使用分号 (;) vs plus (+) 和 exec

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

find . -iname 'A*' -exec echo "{}" \;

Output:

./TOP1/AB
./TOP1/AB/AC
./TOP1/AB/AC/AD
./TOP1/AB/AC/AD/AE
./TOP1/AB/AC/AD/AE/AF

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

另一方面,这就是rm -frv工作方式:

rm -frv ./TOP1

Output:

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'

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

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

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

  • -depth在(父)目录本身之前处理每个目录的内容。 -delete 操作也意味着 -depth。 (即从最底部到顶部摆动 - 就像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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM