February 20, 2008
鼓勵此網誌:1
這幾年Linux 在圖形化界面上有很大的進步,變得更友善,使更多人來接觸Linux
但是純文字的指令一直是很令人著迷的一個特色
善用script 和一些工具(awk,grep…) 可以使工作簡化,work smart 而不是work hard
今天介紹的指令是 xargs
這個指令並不常見,卻很實用
它的工作是將上一個程式輸出的結果轉成下一個程式的參數輸入
範例:
假設有一個目錄如下 (這個樹狀目錄架構是使用 tree 指令所產生的)
.
|-- Makefile
|-- VERSION
|-- VERSION.bak
|-- inc
| |-- fork.h
| |-- main.h
| `-- main.h.bak
`-- src
|-- common_lib
| |-- dl_math.c
| |-- dl_math.c.bak
| |-- dl_string.c
| `-- dl_string.c.bak
|-- fork.c
|-- fork.c.bak
`-- main.c
這是一個程式開發的專案目錄,如果我想要將所有的*.bak 一次清除,那麼該怎麼做呢?
首先我得先找出所有的 *.bak,可以使用 find 指令
可以得到以下的結果
./VERSION.bak
./inc/main.h.bak
./src/fork.c.bak
./src/common_lib/dl_string.c.bak
./src/common_lib/dl_math.c.bak
接下來就是關鍵了
你會怎麼做呢?
1) 把結果使用">" 導向檔案,全部加入 rm (linux 的刪檔指令)嗎?
2) 還是把這些輸出內容變成 rm 的輸入呢?
第一種方式是愚公移山…如果有幾千個檔案…可能會很辛苦~
第二種方式就是使用xargs 來實現我們的理想
紅色部份就是xargs 使用的方式,它會將前面的輸出轉化為它後方指令的參數輸入
執行之後,所有的*.bak 備份檔都被清乾淨了,所有子目錄下的 bak檔也被清除了
很不錯吧~~~^__^
但是這個寫法還有一點缺失…
就是當前方程式沒有任何輸出時…後方的指令就會沒有參數輸入…
以這個例子來看…就會出現這個錯誤訊息
rm: missing operand
Try `rm --help' for more information.
在xargs 裡面有一個參數是 --no-run-if-empty 可以改善上述的問題,當沒前面的程式沒有輸出時,就不執行後面的程式
上述的指令會有如下的效果:
rm ./VERSION.bak ./inc/main.h.bak ./src/fork.c.bak \
./src/common_lib/dl_string.c.bak ./src/common_lib/dl_math.c.bak
20080308補充:
有朋友在問,他想要把過濾出來的檔案copy 或mv 到他指定的目錄,會有錯誤訊息
是滴…因為cp 與mv 能接受的參數形態與rm 不一樣
在 rm 之後的參數都會是要刪掉的,而以cp 為例,有二個必要參數就是來源與目的
依照下列範例就行了~
使用 -i 和 {} 就可以把前面所得到的輸出列表,不是一整串,而是一個一個地傳給後面的指令
上述的指令的效果就像是這樣…
cp ./VERSION.bak ~/bakdir
cp ./inc/main.h.bak ~/bakdir
cp ./src/fork.c.bak ~/bakdir
cp ./src/common_lib/dl_string.c.bak ~/bakdir
cp ./src/common_lib/dl_math.c.bak ~/bakdir
但是純文字的指令一直是很令人著迷的一個特色
善用script 和一些工具(awk,grep…) 可以使工作簡化,work smart 而不是work hard
今天介紹的指令是 xargs
這個指令並不常見,卻很實用
它的工作是將上一個程式輸出的結果轉成下一個程式的參數輸入
範例:
假設有一個目錄如下 (這個樹狀目錄架構是使用 tree 指令所產生的)
.
|-- Makefile
|-- VERSION
|-- VERSION.bak
|-- inc
| |-- fork.h
| |-- main.h
| `-- main.h.bak
`-- src
|-- common_lib
| |-- dl_math.c
| |-- dl_math.c.bak
| |-- dl_string.c
| `-- dl_string.c.bak
|-- fork.c
|-- fork.c.bak
`-- main.c
這是一個程式開發的專案目錄,如果我想要將所有的*.bak 一次清除,那麼該怎麼做呢?
首先我得先找出所有的 *.bak,可以使用 find 指令
| find -iname "*.bak" |
可以得到以下的結果
./VERSION.bak
./inc/main.h.bak
./src/fork.c.bak
./src/common_lib/dl_string.c.bak
./src/common_lib/dl_math.c.bak
接下來就是關鍵了
你會怎麼做呢?
1) 把結果使用">" 導向檔案,全部加入 rm (linux 的刪檔指令)嗎?
2) 還是把這些輸出內容變成 rm 的輸入呢?
第一種方式是愚公移山…如果有幾千個檔案…可能會很辛苦~
第二種方式就是使用xargs 來實現我們的理想
| find -iname "*.bak" | xargs rm |
紅色部份就是xargs 使用的方式,它會將前面的輸出轉化為它後方指令的參數輸入
執行之後,所有的*.bak 備份檔都被清乾淨了,所有子目錄下的 bak檔也被清除了
很不錯吧~~~^__^
但是這個寫法還有一點缺失…
就是當前方程式沒有任何輸出時…後方的指令就會沒有參數輸入…
以這個例子來看…就會出現這個錯誤訊息
rm: missing operand
Try `rm --help' for more information.
在xargs 裡面有一個參數是 --no-run-if-empty 可以改善上述的問題,當沒前面的程式沒有輸出時,就不執行後面的程式
| find -iname "*.bak" | xargs --no-run-if-empty rm |
rm ./VERSION.bak ./inc/main.h.bak ./src/fork.c.bak \
./src/common_lib/dl_string.c.bak ./src/common_lib/dl_math.c.bak
20080308補充:
有朋友在問,他想要把過濾出來的檔案copy 或mv 到他指定的目錄,會有錯誤訊息
是滴…因為cp 與mv 能接受的參數形態與rm 不一樣
在 rm 之後的參數都會是要刪掉的,而以cp 為例,有二個必要參數就是來源與目的
依照下列範例就行了~
| find -iname "*.bak" | xargs -i cp {} ~/bakdir |
上述的指令的效果就像是這樣…
cp ./VERSION.bak ~/bakdir
cp ./inc/main.h.bak ~/bakdir
cp ./src/fork.c.bak ~/bakdir
cp ./src/common_lib/dl_string.c.bak ~/bakdir
cp ./src/common_lib/dl_math.c.bak ~/bakdir
本著作係採用創用 CC 姓名標示-非商業性-禁止改作 2.5 Taiwan 授權條款授權.


































































