如何使用缺少 -exec 的 find 遞歸設定目錄權限?

如何使用缺少 -exec 的 find 遞歸設定目錄權限?

find我的 Qnap NAS 被一個缺少參數的命令所困擾-exec,所以我必須透過管道傳輸某些內容。 shell 是:GNU bash,版本 3.2.57(2)-release-(arm-unknown-linux-gnueabihf)

我試圖在當前目錄的所有子目錄(而不是檔案)上設定 setgid 位元。

這不起作用:

find . -type d | xargs chmod g+s $1

使用"$1""$(1)"$("1")也不起作用。它們都表示chmod正在傳遞一個包含空格作為兩個或多個參數的目錄名稱(它會輸出有關支援哪些參數的標準幫助訊息)。

xargs如果不是必須的話我不會用;我覺得長名字還是會讓人窒息,不是嗎?

這些及其變體不起作用:

find . -type d | chmod g+s

find . -type d | chmod g+s "$1"

我考慮過使用awksed註入引號,但我必須認為有一種更簡單的方法可以做到這一點。人們之前做了什麼-exec? (可悲的是,我可能在 1995 年左右就知道了,但早已忘記了。)

PS:這些目錄名稱中的各種都會包含Unicode字元、符號?等。也就是說,我可能應該?用 Unicode 字元之類的東西替換所有實例,這樣 Windows 就不會因為它們而卡住。但這也需要find對這個殘件版本的find.

答案1

的輸出發出由換行符1find分隔的檔案名稱。這不是想要的格式,也無法產生想要的格式:它將其輸入解析為空格分隔的項目,並用於引用。某些版本可以採用換行符號分隔的輸入,但如果您缺乏標準選項,您也可能會這樣做。xargsfindxargs\'"xargsfindxargs

find . -type d | xargs chmod g+s只要您的目錄名稱不包含空格或\'".請注意,沒有$1: 這對 shell 有意義,但沒有 shell 參與解析 的輸出find並將其提供給chmod, only xargs

如果您的findhas-print0xargshas -0,您可以使用這些選項來傳遞空分隔的檔案名,這適用於任意檔案名稱。

find . -type d -print0 | xargs -0 chmod g+s

如果您xargs支援標準選項-I,您可以使用它來指示它將每一行作為一個項目來處理,而不是用空格分隔的帶引號的字串。這可以處理空格,但不能處理\"'換行符。

find . -type d | xargs -I {} chmod g+s {}

您可以使用 shell 來循環行而不是xargs.這適用於任何不包含換行符的檔案名稱。

find . -type d | while IFS= read -r line; do chmod g+s "$line"; done

這兩種解決方案僅適用於不包含換行符號的檔案名稱。 with filenames contains newlines的輸出find是不明確的,除非有一種情況很難解析:find不會自發地發出多個斜杠,因此如果您輸入//要遍歷的目錄的路徑,您可以在輸出中識別出這一點。以下是一些經過最低限度測試的程式碼,它使用這個事實將輸出從 轉換find為 的輸入格式xargs

chars=$(printf '\t "'\\\')
{ find .//. -type d; echo .// } | LC_ALL=C sed -n '
s/['"$chars"']/\\&/g
/^\.\/\// {
x
s/\n/\\&/g
p
b
}
H' | LC_ALL=C xargs chmod g+s

1 更準確地說:以換行符終止(姓氏後面有一個換行符)。

答案2

你可以用 bash 自己進行遞歸。就像是:

shopt -s nullglob dotglob
recurse_chmod () (
  cd "$1"
  for d in ./*/
  do
    if [ -L "$d" ]; then continue; fi
    chmod g+s "$d"
    recurse_chmod "$d"
  done
)
recurse_chmod .

答案3

您可以告訴 xargs 使用 \0 作為分隔符find . -type d -print0 | xargs -0 chmod g+s

或者

find . -type d | xargs -I{} -d '\n' chmod g+s "{}"。它將使用 \n 作為分隔符號。

相關內容