find -exec 與透過 xargs 進行管道傳輸之間的不同行為

find -exec 與透過 xargs 進行管道傳輸之間的不同行為

我想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)

答案1

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

為了說明這一點,讓我們考慮一個包含三個常規檔案的目錄:

$ 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 "*"在原始命令中,和 之間沒有運算符-exec ... \;。因此,find假定預設運算子是邏輯與。因為邏輯與比邏輯或 ( -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僅有的操作員。

相關內容