Bash
find -exec 和通過 xargs 管道之間的不同行為
我想
chmod go+w
在包含隱藏文件的特定文件夾中遞歸執行,我首先嘗試了find . -name ".*" -o -name "*" -exec chmod go+w {} \;
但我發現它並沒有影響隱藏文件。為了檢查自己,我跑了
find . -name ".*" -o -name "*"
並列出了隱藏文件。我還注意到,如果我排除了該
-o -name "*"
部分,它將對隱藏文件進行 chmod(但當然排除非隱藏文件)。我最後一次嘗試是改用 xargsfind . -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
讓我們嘗試使用一個簡單的
$ find . -name ".*" -o -name "*" -print ./not_hidden
如您所見,與上面的隱含邏輯-and
-name "*"
但是,請考慮在沒有指定任何操作的情況下會發生什麼:
$ find . -name ".*" -o -name "*" . ./not_hidden ./.hidden1 ./.hidden2
在這裡,找到了所有文件。原因是,在這個版本中,
-o
是唯一的運營商。