關於bash指令 - Linux

Table of Contents

※ 引述《ymzk ()》之銘言:
> 在網路上有看到一個方法可以把某個目錄下所有資料夾都變成群組可執行
> 指令如下
> sudo chmod g+x $(find ./ -type d)

$() 裡面可以放入要執行的命令,最後 find 命令透過 stdout 輸出的訊息
當作為 chmod g+x 傳入的檔案目錄名稱。

其實不建議這樣用,因為路徑若有空白這類情況時候會出錯

> 但我執行時會出現一些怪怪的訊息, 例如一些資料夾他說根本找不到

比方有個目錄名稱叫做 "My Documents" 來說,上面語法就變成:

sudo chmod g+x My Documents

一般要避免該問題有很多方式,比方:

find ./ -type d -exec chmod g+s {} \;

不過這語法效能很糟糕,因為有找到 10000 個項目就要呼叫 chmod 高達
10000 次,所以一般會改用:

find ./ -type d | xargs chmod g+s

其中 find 找到符合的列表會透過 stdout 輸出,xargs 能夠透過 stdin 讀入
剛剛 find 給的輸出結果,然後當作為執行 chmod g+s 要帶入的引數。所以這
語法基本上類似於 chmod g+s $(find ./ -type d)

當然上面那語法也會遇到檔案有空白等問題,有空白字元等檔名會被當作兩個
項目。所以一般使用會使用:

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

其中 find 搭配 -print0 就是透過 stdout 輸出的列表內改用 NULL 字元當檔名
分隔,而不是使用原本一般的空白字元。而要呼叫 xargs 時候也要傳入 -0 告知
讀入的資料以 NULL 字元當分隔,如此就可以解決剛剛談到的問題。

find + xargs 基本上效能不錯,不過有時候 find 結果帶多可能會讓 xargs 在
帶入結果時候發生執行命令帶入引數發生 Argument list too long 的錯誤,一般
要避開可以這樣:

find ./ -type d -print0 | xargs -n 100 -0 chmod g+

就是一次處理單位為 100

> 另問一下這到底是什麼原理?
> 他是執行了很多chmod指令還是一個chmod指令後面帶了很長的參數?
> 如果是後者會不會因為太長而有部份失敗@@"

--

All Comments

Hedy avatarHedy2016-05-04
推小州老師講解。
Elma avatarElma2016-05-06
推 平時沒處理到那麼多還真的不會考慮到
Elma avatarElma2016-05-07
推小州老師講解
Lauren avatarLauren2016-05-09
好強,謝謝分享
Carol avatarCarol2016-05-10
為什麼用xargs的效能會好過用exec參數?
Oscar avatarOscar2016-05-14
剛剛看了 find 的 manpage 說 \; 換成 + 也會有類似效果 @@
Andrew avatarAndrew2016-05-19
xargs其實很類似於$()的功能 不過xargs比較彈性
James avatarJames2016-05-20
是因為那個語法是把前面find找出來的pile給xargs後面接的指
令,一次做完。這樣就不用call很多次exec後面的指令
pipe 我打成了甚麼..
Liam avatarLiam2016-05-21
白話一點差不多就是
chmod file1
chmod file2
chmod file3

chmod file1 file2 file3
的差別
Lydia avatarLydia2016-05-23
目前的 find 應該都可以吃 -exec {} + 語法
Dinah avatarDinah2016-05-24
這就的確與 xargs 行為類似,所以也不一定需要 xargs 了