簡體   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