Bash

find -exec 和通過 xargs 管道之間的不同行為

  • May 24, 2017

我想chmod go+w在包含隱藏文件的特定文件夾中遞歸執行,我首先嘗試了

find . -name ".*" -o -name "*" -exec chmod go+w {} \;

但我發現它並沒有影響隱藏文件。為了檢查自己,我跑了

find . -name ".*" -o -name "*"

並列出了隱藏文件。我還注意到,如果我排除了該-o -name "*"部分,它將對隱藏文件進行 chmod(但當然排除非隱藏文件)。我最後一次嘗試是改用 xargs

find . -name ".*" -o -name "*" | xargs chmod go+w

最終按預期工作。我在第一個片段中做錯了什麼?

紅帽企業 Linux 伺服器 6.8 版(聖地亞哥)

GNU bash,版本 4.3.42(1)-release (x86_64-unknown-linux-gnu)

解決方案是將兩個名稱測試與括號綁定在一起。

為了說明這一點,讓我們考慮一個包含三個正常文件的目錄:

$ ls -a
.  ..  .hidden1  .hidden2  not_hidden

現在,讓我們使用原始命令:

$ find . -name ".*" -o -name "*" -exec echo Found {} \;
Found ./not_hidden

僅找到非隱藏文件。

接下來,讓我們添加括號將兩個名稱測試組合在一起:

$ find . \( -name ".*" -o -name "*" \) -exec echo Found {} \;
Found .
Found ./not_hidden
Found ./.hidden1
Found ./.hidden2

找到所有文件。

解決方案是使用括號。

更多細節

-name "*"在原始命令中, and 之間沒有運算符-exec ... \;。因此,find假定預設運算符是邏輯與。因為logical-and 比logical-or ( -o) 綁定更緊密,這意味著該命令被解釋為:

find . \( -name ".*" \) -o \( -name "*" -exec echo Found {} \; \)

這意味著exec僅當第一個name條件不匹配時才執行。

有關詳細資訊,請參閱 中的操作員部分man find

沒有會發生什麼-exec

讓我們嘗試使用一個簡單的-print

$ find . -name ".*" -o -name "*" -print
./not_hidden

如您所見,與上面的隱含邏輯-and-print綁定到。-name "*"

但是,請考慮在沒有指定任何操作的情況下會發生什麼:

$ find . -name ".*" -o -name "*"
.
./not_hidden
./.hidden1
./.hidden2

在這裡,找到了所有文件。原因是,在這個版本中,-o唯一的運營商。

引用自:https://unix.stackexchange.com/questions/367071