本身的《Linux系統管理初學者指南--基於CentOS 7.6》已於2019年10月份出版,對於這本書的質量整體上感受還算滿意,可是限於當時的知識水平,有些地方描述的仍然不是很清楚,因此在講課的過程當中也在不斷進行修訂。好比最近在講到find命令的處理動做時,很多學生就提出疑問,於是我對原書中這部份內容進行了重寫,但願再版時能夠訂正。
linux
find命令不只能夠查找,還能夠對找到的結果進行進一步的處理,這就要用到「處理動做」。
例如,找出/usr/bin目錄中全部的符號連接文件。[root@localhost ~]# find /usr/bin -type l
上面這條命令查找出來的結果只顯示文件名,若是咱們還想查看每一個符號連接文件都指向了哪一個源文件,就能夠在find命令的最後加上處理動做「-ls」。ssh
[root@localhost ~]# find /usr/bin -type l -ls 50346791 0 lrwxrwxrwx 1 root root 3 2月 14 2019 /usr/bin/captoinfo -> tic
須要注意的是,這個處理動做「-ls」屬因而find命令的一部分,而並不是是以前所介紹的ls命令,於是沒法在處理動做「-ls」以後加上ls命令的各類選項。例如,咱們但願找出/etc目錄中全部大小在1MB以上的文件,並人性化顯示其詳細信息,那麼執行下面的命令就會報錯。ide
[root@localhost ~]# find /etc -size +1M -ls -lh find: 未知的斷言「-lh」
要實現這個需求,就要藉助於find命令的另一個處理動做「-exec」。這個處理動做能夠將find命令找到的結果看成文件去處理,在「-exec」的後面要跟上進一步處理所要執行的命令,另外在命令中還須要使用符號「{}」表示find命令查找到的結果,在命令的最後必須添加「 \;」表示命令結束(注意前面有個空格)。
例如,找出/etc目錄中全部大小在1MB以上的文件,並人性化顯示其詳細信息,下面這條命令纔是正確的作法。在這條命令中,ls就是以前所介紹的ls命令,咱們藉助於-exec將find命令找到的結果,以文件的形式傳給ls命令繼續處理。測試
[root@localhost ~]# find /etc -size +1M -exec ls -lh {} \; -rw-------. 1 root root 3.8M 11月 3 2018 /etc/selinux/targeted/active/policy.kern
再好比,找出/tmp目錄中全部後綴爲「.txt」的文件並將其刪除。[root@localhost ~]# find /tmp -name "*.txt" -exec rm -f {} \;
不少同窗在這裏會疑惑,爲何這裏用管道符「|」(將在2.9.5節介紹)沒法實現上面的操做呢?好比咱們作下面的測試:code
[root@localhost ~]# touch /tmp/{a,b,c}.txt #在/tmp目錄中生成3個測試文件 [root@localhost ~]# find /tmp -name "*.txt" | rm -f #利用管道結合rm刪除 [root@localhost ~]# find /tmp -name "*.txt" #測試文件仍然存在 /tmp/a.txt /tmp/b.txt /tmp/c.txt [root@localhost ~]# find /tmp -name "*.txt" -exec rm -f {} \; #利用exec結合rm刪除 [root@localhost ~]# find /tmp -name "*.txt" #測試文件被成功刪除
處理動做-exec最主要的做用就是能夠將find命令找到的結果當成文件去處理,而默認狀況下,find命令找到的結果是被看成文本信息去處理的。
怎樣理解上面這段話呢?好比對於執行「find /tmp -name "*.txt"」命令所找到的三個文件:/tmp/a.txt、/tmp/b.txt、/tmp/c.txt,默認狀況下find命令只是把符合查找條件的這三個文件找到,並把它們的名字在屏幕上輸出,於是咱們在屏幕上所看到的只是三行文本信息。對於文本信息,可使用以前介紹的文件內容操做命令進行處理,好比用wc命令統計行數,用grep命令進行過濾等。對象
[root@localhost ~]# find /tmp -name "*.txt" | wc -l #統計find找到的文件數量 3 [root@localhost ~]# find /tmp -name "*.txt" | grep 'a' #對find的結果進行過濾 /tmp/a.txt
對於文本信息,以前介紹的文件和目錄操做命令就沒法處理了,好比cp、mv、rm等,由於這些命令所操做的對象必須是文件。此時-exec就能夠派上用場,由於它的主要做用就是能夠將find命令找到的結果再也不看做是文本信息,而是看做文件。於是若是須要對find的結果用文件操做命令進行進一步處理的話,那麼就須要結合-exec。
例如,查找/boot目錄下的以「init」開頭的文件,並將其複製到/tmp目錄。[root@localhost ~]# find /boot -name "init*" -exec cp {} /tmp \;
除了-ls和-exec以外,還有一個比較經常使用的處理動做是-delete,它能夠將find找到的結果直接刪除。
例如以前的操做:找出/tmp目錄中全部後綴爲「.txt」的文件並將其刪除。其實更爲簡便的作法是下面的命令:[root@localhost ~]# find /tmp -name "*.txt" -delete
blog
當在find命令中利用-exec對查找到的結果進行進一步處理時,有時可能會出現問題。這是由於-exec是將find所找到的結果一次性地送給後面的命令進行處理,有時候find可能會找到大量的文件,超出了後面的命令所能處理的參數範圍,這時就會出現溢出錯誤,錯誤信息一般是「參數列太長」或「參數列溢出」,這時就可使用xargs命令。xargs雖然自己是一個獨立的Linux命令,但一般都是被用來配合find命令使用。經過xargs,能夠將find所找到的結果分批次地送給以後的命令進行處理,從而避免出現溢出問題。
xargs命令須要經過管道與find命令配合使用,xargs的命令格式「find ……| xargs commands」。
下面咱們先準備一個測試文件。get
[root@localhost ~]# mkdir /tmp/pass [root@localhost ~]# echo "password:123" >> /tmp/pass/test.txt
假設在/tmp目錄中存放了大量的文件,在其中的某個文件裏存放了一個密碼,關鍵字爲「password」,咱們如今但願可以將這個存放了密碼的文件找出來。
若是利用find命令的-exec選項,能夠執行下面的命令:it
[root@localhost ~]# find /tmp -type f -exec grep "password" {} \; password:123
能夠發現,雖然經過上面的命令找出了密碼,但並無顯示存放該密碼的文件名。下面換作用xargs命令來實現該要求,xargs就能夠將關鍵字所在的文件一併顯示出來。class
[root@localhost ~]# find /tmp -type f | xargs grep "password" /tmp/pass/test.txt:password:123
再好比,咱們但願將/tmp目錄以及/tmp全部下級子目錄中,文件名以「.txt」做爲後綴的文件都複製到/root目錄中。若是用find命令的-exec來實現:[root@localhost ~]# find /tmp -name "*.txt" -exec cp {} /root \;
若是用xargs命令來實現,一樣須要用「{}」來代指find命令查找到的結果,而且須要爲xargs命令添加-i選項。[root@localhost ~]# find /tmp -name "*.txt" | xargs -i cp {} /root
經過這幾個實例能夠發現,xargs命令與find命令-exec處理動做的功能基本相同,因此若是-exec能夠知足要求,那麼就無需使用xargs命令。xargs命令的主要用途在於它能夠對find命令找到的結果分批處理,避免出現溢出錯誤。
好比在/etc目錄中一共有2507個普通文件。
[root@localhost ~]# find /etc -type f | wc -l 2507
若是咱們但願能找出/etc目錄中全部包含關鍵字「PermitRootLogin」的文件,分別用這兩種方法來實現:
[root@localhost ~]# find /etc -type f -exec grep "PermitRootLogin" {} \; #PermitRootLogin yes # the setting of "PermitRootLogin without-password". [root@localhost ~]# find /etc -type f | xargs grep "PermitRootLogin" /etc/ssh/sshd_config:#PermitRootLogin yes /etc/ssh/sshd_config:# the setting of "PermitRootLogin without-password".
能夠發如今用-exec的方法實現時,出現了明顯的卡頓,若是數據量再大一些的話,可能就會致使溢出。而用xargs命令來實現,一方面更爲快速,另外一方面不會出現溢出問題,並且顯示的內容也更爲詳細。因此在進行這類操做時,更加推薦使用xargs命令。