為什麼 `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 {} +

這並不完美;嵌套目錄或大量匹配目錄仍然可能導致列印錯誤訊息,但這應該適用於問題的簡單情況。

相關內容