
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"
我考慮過使用awk
或sed
註入引號,但我必須認為有一種更簡單的方法可以做到這一點。人們之前做了什麼-exec
? (可悲的是,我可能在 1995 年左右就知道了,但早已忘記了。)
PS:這些目錄名稱中的各種都會包含Unicode字元、符號?
等。也就是說,我可能應該?
用 Unicode 字元之類的東西替換所有實例,⁇
這樣 Windows 就不會因為它們而卡住。但這也需要find
對這個殘件版本的find
.
答案1
的輸出發出由換行符1find
分隔的檔案名稱。這不是想要的格式,也無法產生想要的格式:它將其輸入解析為空格分隔的項目,並用於引用。某些版本可以採用換行符號分隔的輸入,但如果您缺乏標準選項,您也可能會這樣做。xargs
find
xargs
\'"
xargs
find
xargs
find . -type d | xargs chmod g+s
只要您的目錄名稱不包含空格或\'"
.請注意,沒有$1
: 這對 shell 有意義,但沒有 shell 參與解析 的輸出find
並將其提供給chmod
, only xargs
。
如果您的find
has-print0
和xargs
has -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 作為分隔符號。