【Linux】- 對find,xargs,grep和管道的一些理解


問題

相信大家都知道在目錄中搜索含有固定字符串文件的命令:

find . -name '*.py' |xargs grep test

剛開始的時候,我不熟悉xargs命令,所以直接使用的命令是:

find . -name '*.py' |grep test

結果並不是自己所期望的。此命令只是找出文件名中包含"test"的文件。

本文旨在揭示xargs究竟做了什么,使得結果不一樣。

參數與標准輸入

這兩個詞在Linux命令中是很常見的。但是參數和標准輸入其實是有區別的。我們日常使用的很多命令,例如:ls -lah .中。l、 a、 h 、.都是命令ls的參數。至於標准輸入,可以說它是某種流數據。而通常來講標准輸入的流數據來源就是我們的終端輸入。在Linux命令中,有些命令可以接收標准輸入,有些是不能的。像上面的ls,就是只能接收參數,不能接收標准輸入。像cat命令或echo命令,這些是可以的。

怎么分辨一個命令可不可以接收標准輸入?很簡單,當你敲完命令回車后,終端會等待接收你的輸入,例如當你在終端輸入cat后,終端會等待你輸入字符,當你輸入一些字符后,然后按Ctrl-C發送終止符號。這時cat命令接收標准輸入完畢,執行命令,也就是將剛才鍵入的內容輸出的標准輸出上(屏幕)。

管道

管道的作用是將前面命令的標准輸出作為后面命令的標准輸入。這里要注意,后面的命令接收的是標准輸入,所以如果命令不支持接收標准輸入,那么就不能直接使用管道,例如常用的ls命令,只能使用參數,而不能使用標准輸入,所以[command] | ls是不能使用的。而命令如echocat就可以。那么肯定有方法來實現這些不能使用標准輸入的命令與管道結合,這時候xargs便出場了。

xargs命令

xargs命令通俗來講就是將標准輸入轉成各種格式化的參數,所以命令[command 1] | xargs [command 2]就是將command 1的標准輸出結果,通過管道|變成xargs的標准輸入,然后xargs再將此標准輸入變成參數,傳給[command 2]。這樣一來,通過xargs命令,我們便可以在管道后面使用那些不接收標准輸入的命令了。例如[command 1]|xargs ls,是不是很熟悉?

find與grep

有了以上的知識點,到這里終於可以解答最開始的問題了。為什么命令:

find . -name '*.py' |grep test

find . -name '*.py' |xargs grep test

的結果是不一樣的了。

我們首先來查看grep手冊。通過man grep命令:

DESCRIPTION
       grep searches the named input FILEs (or standard input if no files are named, or if a single hyphen-minus (-) is given as file name) for lines containing a match to the given PATTERN.  
By default, grep prints the matching lines.

可以看到grep是支持標准輸入的。

假設目錄存在如下文件:

$ ls
Altitest.py  python.py  runora.py  test.py  TransferFile.py

那么對於第一個命令:find . -name '*.py' |grep test,是將前面命令的標准輸出作為標准輸入傳給了grep test,那么grep是從這些標准輸入尋找test字符,也就是文件名組成的字符流。

$ find . -name '*.py' |grep test
./Altitest.py
./test.py

可以看到最終選擇出的是這些文件名。

而對於第二個命令:find . -name '*.py' |xargs grep test,通過xargsfind得到的文件名成為了參數傳給后面的grep,那么這時候這些文件名就是實實在在的文件標識,grep接收后會按正常的使用方式在各文件中搜尋字符串。

#find . -name '*.py' |xargs grep test
./runora.py:testConn = cx_Oracle.connect('user/passwd@tns')
./runora.py:testCursor = testConn.cursor()
./runora.py:testCursor.execute("select * from table")
./runora.py:rows = testCursor.fetchall()
./runora.py:testCursor.close()
./runora.py:testConn.close()

到這里算是將findgrepxargs和管道的作用理解清楚了。

 

轉自:http://fatmouse.xyz/2016/05/10/2016-05-10-find-grep-xargs-and-pipe/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM