轉自於:http://fatmouse.xyz/2016/05/10/2016-05-10-find-grep-xargs-and-pipe/python
相信你們都知道在目錄中搜索含有固定字符串文件的命令:fetch
1 |
find . -name '*.py' |xargs grep test |
剛開始的時候,我不熟悉xargs
命令,因此直接使用的命令是spa
1 |
find . -name '*.py' |grep test |
結果並非本身所指望的。此命令只是找出文件名*.txt
有test
的狀況。code
這裏我就研究一下,究竟xargs
作了什麼,使得結果不相同。ip
這兩個詞咱們在Linux命令中是很常見的。可是參數和標準輸入實際上是有區別的。咱們平常使用的不少命令,例如ls -lah .
中。l
, a
, h
,.
都是命令ls
的參數。至於標準輸入,能夠說它某種流數據。而一般來說標準輸入的流數據來源就是咱們的終端輸入。在Linux命令中,有些命令能夠接收標準輸入,有些是不能的。像上面的ls
,就是隻能接收參數,不能接收標準輸入。像cat
命令或echo
命令,這些是能夠的。字符串
怎麼分辨一個命令可不能夠接收標準輸入?很簡單,當你敲完命令回車後,終端會等待接收你的輸入,例如當你在終端輸入cat
後,終端會等待你輸入字符,當你輸入一些字符後,而後按Ctrl-C
發送終止符號。這時cat
命令接收標準輸入完畢,執行命令,也就是將剛纔鍵入的內容輸出的標準輸出上(屏幕)。input
管道的做用是將前面命令的標準輸出做爲後面命令的標準輸入。這裏要注意,後面的命令接收的是標準輸入,因此若是命令不支持接收標準輸入,那麼就不能直接使用管道,例如經常使用的ls
命令,只能使用參數,而不能使用標準輸入,因此[command] | ls
是不能使用的。而命令如echo
或cat
就能夠。那麼確定有方法來實現這些不能使用標準輸入的命令與管道結合,這時候xargs
便出場了。it
xargs
命令通俗來說就是將標準輸入轉成各類格式化的參數,因此命令[command 1] | xargs [command 2]
就是將command 1
的標準輸出結果,經過管道|
變成xargs
的標準輸入,而後xargs
再將此標準輸入變成參數,傳給[command 2]
。這樣一來,經過xargs
命令,咱們即可以在管道後面使用那些不接收標準輸入的命令了。例如[command 1]|xargs ls
,是否是很熟悉?pip
有了以上的知識點,到這裏終於能夠解答最開始的問題了。爲何命令table
1 |
find . -name '*.py' |grep test |
和
1 |
find . -name '*.py' |xargs grep test |
的結果是不同的了。
咱們首先來查看grep手冊。經過man grep
命令。
1 |
DESCRIPTION |
這裏能夠看到grep是支持標準輸入的。
假設目錄存在以下文件:
1 |
$ ls |
那麼對於第一個命令find . -name '*.py' |grep test
,是將前面命令的標準輸出做爲標準輸入傳給了grep test
,那麼grep
是從這些標準輸入尋找test
字符,也就是文件名組成的字符流
1 |
$ find . -name '*.py' |grep test |
能夠看到最終選擇出的是這些文件名。
而對於第二個命令find . -name '*.py' |xargs grep test
,經過xargs
,find
獲得的文件名成爲了參數傳給後面的grep
,那麼這時候這些文件名就是實實在在的文件標識,grep
接收後會按正常的使用方式在各文件中搜尋字符串。
1 |
#find . -name '*.py' |xargs grep test |
到這裏算是將find
,grep
,xargs
和管道的做用理解清楚了。
xargs
還有指定參數位置的做用。假設咱們要將目錄下全部的.py
文件放到Python目錄中去,能夠使用命令find . -name '*.py' | xargs -I {} mv {} ./Python
參數-I
指定了管道前命令做爲參數所應該在管道後面命令的位置。咱們在查看不少命令手冊時,手冊會說明命令的使用方法。例如
grep [OPTIONS] PATTERN [FILE...]
,也就是命令的最後一個位置是文件名[FILE]。
這裏要注意這個文件名[FILE]也是參數。