A. linux里find 和 xargs 請舉例兩個同等功效的例子
使用find和xargs
有時可能需要在系統中查找具有某一特徵的文件(例如文件許可權、文件屬主、文件長度、文件類型等等)。這樣做可能有很多原因。可能出於安全性的考慮,或是一般性的系統管理任務,或許只是為了找出一個不知保存在什麼地方的文件。F i n d是一個非常有效的工具,它可以遍歷當前目錄甚至於整個文件系統來查找某些文件或目錄。
在本章中,我們介紹以下內容:
�6�1 find命令選項。
�6�1 使用f i n d命令不同選項的例子。
�6�1 配合f i n d使用x a rg s命令的例子。
由於f i n d具有如此強大的功能,所以它的選項也很多,其中大部分選項都值得我們花時間
來了解一下。即使系統中含有網路文件系統( N F S ),f i n d命令在該文件系統中同樣有效,只要你具有相應的許可權。
在運行一個非常消耗資源的f i n d命令時,很多人都傾向於把它放在後台執行,因為遍歷一個大的文件系統可能會花費很長的時間(這里是指3 0 G位元組以上的文件系統)。
F i n d命令的一般形式為:
find pathname -options [-print -exec -ok]
讓我們來看看該命令的參數:
pathname find命令所查找的目錄路徑。例如用.來表示當前目錄,用/來表示系統根目錄。
-print find命令將匹配的文件輸出到標准輸出。
-exec find命令對匹配的文件執行該參數所給出的s h e l l命令。相應命令的形式為' c o m m -
and' {} \;,注意{ }和\;之間的空格。
-ok 和- e x e c的作用相同,只不過以一種更為安全的模式來執行該參數所給出的s h e l l命令,
在執行每一個命令之前,都會給出提示,讓用戶來確定是否執行。
find命令選項
f i n d命令有很多選項或表達式,每一個選項前面跟隨一個橫杠-。讓我們先來看一下該命
令的主要選項,然後再給出一些例子。
-name 按照文件名查找文件。
-perm 按照文件許可權來查找文件。
-prune 使用這一選項可以使f i n d命令不在當前指定的目錄中查找,如果同時使用了- d e p t h
選項,那麼- p r u n e選項將被f i n d命令忽略。
-user 按照文件屬主來查找文件。
-group 按照文件所屬的組來查找文件。
-mtime -n +n 按照文件的更改時間來查找文件, - n表示文件更改時間距現在n天以內,+ n
表示文件更改時間距現在n天以前。F i n d命令還有- a t i m e和- c t i m e選項,但它們都和- m t i m e選項
相似,所以我們在這里只介紹- m t i m e選項。
-nogroup 查找無有效所屬組的文件,即該文件所屬的組在/ e t c / g r o u p s中不存在。
-nouser 查找無有效屬主的文件,即該文件的屬主在/ e t c / p a s s w d中不存在。
-newer file1 ! file2 查找更改時間比文件f i l e 1新但比文件f i l e 2舊的文件。
-type 查找某一類型的文件,諸如:
b - 塊設備文件。
d - 目錄。
c - 字元設備文件。
p - 管道文件。
l - 符號鏈接文件。
f - 普通文件。
-size n[c] 查找文件長度為n塊的文件,帶有c時表示文件長度以位元組計。
-depth 在查找文件時,首先查找當前目錄中的文件,然後再在其子目錄中查找。
-fstype 查找位於某一類型文件系統中的文件,這些文件系統類型通常可以在配置文件
/ e t c / f s t a b中找到,該配置文件中包含了本系統中有關文件系統的信息。
-mount 在查找文件時不跨越文件系統m o u n t點。
-follow 如果f i n d命令遇到符號鏈接文件,就跟蹤至鏈接所指向的文件。
-cpio 對匹配的文件使用c p i o命令,將這些文件備份到磁帶設備中。
使用name選項
文件名選項是f i n d命令最常用的選項,要麼單獨使用該選項,要麼和其他選項一起使用。
可以使用某種文件名模式來匹配文件,記住要用引號將文件名模式引起來。
不管當前路徑是什麼,如果想要在自己的根目錄$ H O M E中查找文件名符合* . t x t的文件,
使用~作為' p a t h n a m e參數,波浪號~代表了你的$ H O M E目錄。
$ find ~ -name "*.txt" -print
想要在當前目錄及子目錄中查找所有的『 * . t x t』文件,可以用:
$ find . -name "*.txt" -print
想要的當前目錄及子目錄中查找文件名以一個大寫字母開頭的文件,可以用:
$ find . -name "[A-Z]*" -print
想要在/ e t c目錄中查找文件名以h o s t開頭的文件,可以用:
$ find /etc -name "host*" -print
想要查找$ H O M E目錄中的文件,可以用:
$ find ~ -name "*" -pri或ntf ind . -print
要想讓系統高負荷運行,就從根目錄開始查找所有的文件。如果希望在系統管理員那裡
保留一個好印象的話,最好在這么做之前考慮清楚!
$ find / -name "*" -print
如果想在當前目錄查找文件名以兩個小寫字母開頭,跟著是兩個數字,最後是* . t x t的文件,下面的命令就能夠返回名為a x 3 7 . t x t的文件:
$ find . -name "[a-z][a-z][0--9][0--9].txt" -print
使用perm選項
如果希望按照文件許可權模式來查找文件的話,可以採用- p e r m選項。你可能需要找到所有
用戶都具有執行許可權的文件,或是希望查看某個用戶目錄下的文件許可權類型。在使用這一選
項的時候,最好使用八進制的許可權表示法。
為了在當前目錄下查找文件許可權位為7 5 5的文件,即文件屬主可以讀、寫、執行,其他用
戶可以讀、執行的文件,可以用:
$ find . -perm 755 -print
如果希望在當前目錄下查找所有用戶都可讀、寫、執行的文件(要小心這種情況),我們
可以使用f i n d命令的- p e r m選項。在八進制數字前面要加一個橫杠-。在下面的命令中- p e r m代
表按照文件許可權查找,而『 0 0 7』和你在c h m o d命令的絕對模式中所採用的表示法完全相同。
$ find . -perm -007 -print
忽略某個目錄
如果在查找文件時希望忽略某個目錄,因為你知道那個目錄中沒有你所要查找的文件,
那麼可以使用- p r u n e選項來指出需要忽略的目錄。在使用- p r u n e選項時要當心,因為如果你同
時使用了- d e p t h選項,那麼- p r u n e選項就會被f i n d命令忽略。
如果希望在/ a p p s目錄下查找文件,但不希望在/ a p p s / b i n目錄下查找,可以用:
$ find /apps -name "/apps/bin" -prune -o -print
使用user和nouser選項
如果希望按照文件屬主查找文件,可以給出相應的用戶名。例如,在$ H O M E目錄中查找
文件屬主為d a v e的文件,可以用:
$ find ~ -user dave -print
在/ e t c目錄下查找文件屬主為u u c p的文件:
$ find /etc -user uucp -print
為了查找屬主帳戶已經被刪除的文件,可以使用- n o u s e r選項。這樣就能夠找到那些屬主
在/ e t c / p a s s w d文件中沒有有效帳戶的文件。在使用- n o u s e r選項時,不必給出用戶名; f i n d命令
能夠為你完成相應的工作。例如,希望在/ h o m e目錄下查找所有的這類文件,可以用:
$ find /home -nouser -print
使用group和nogroup選項
就像u s e r和n o u s e r選項一樣,針對文件所屬於的用戶組, f i n d命令也具有同樣的選項,為
了在/ a p p s目錄下查找屬於a c c t s用戶組的文件,可以用:
$ find /apps -group accts -print
要查找沒有有效所屬用戶組的所有文件,可以使用n o g r o u p選項。下面的f i n d命令從文件
系統的根目錄處查找這樣的文件
$ fine/-nogroup-print
按照更改時間查找文件
如果希望按照更改時間來查找文件,可以使用m t i m e選項。如果系統突然沒有可用空間了,
很有可能某一個文件的長度在此期間增長迅速,這時就可以用m t i m e選項來查找這樣的文件。
用減號-來限定更改時間在距今n日以內的文件,而用加號+來限定更改時間在距今n日以前的
文件。
希望在系統根目錄下查找更改時間在5日以內的文件,可以用:
$ find / -mtime -5 -print
為了在/ v a r / a d m目錄下查找更改時間在3日以前的文件,可以用:
$ find /var/adm -mtime +3 -print
查找比某個文件新或舊的文件
如果希望查找更改時間比某個文件新但比另一個文件舊的所有文件,可以使用- n e w e r選
項。它的一般形式為:
newest_file_name ! oldest_file_name
其中,!是邏輯非符號。
這里有兩個文件,它們的更改時間大約相差兩天。
下面給出的f i n d命令能夠查找更改時間比文件a g e . a w k新但比文件b e l t s . a w k舊的文件:
如果想使用f i n d命令的這一選項來查找更改時間在兩個小時以內的文件,除非有一個現成的文件其更改時間恰好在兩個小時以前,否則就沒有可用來比較更改時間的文件。為了解決這一問題,可以首先創建一個文件並將其日期和時間戳設置為所需要的時間。這可以用t o u c h命令來實現。
假設現在的時間是2 3 : 4 0,希望查找更改時間在兩個小時以內的文件,可以首先創建這樣一個文件:一個符合要求的文件已經被創建;這里我們假設今天是五月四日,而該文件的更改時間是2 1 : 4 0,比現在剛好早兩個小時。
現在我們就可以使用f i n d命令的- n e w e r選項在當前目錄下查找所有更改時間在兩個小時以內的文件:
$ find . -newer dstamp -print
使用type選項
U N I X或L I N U X系統中有若干種不同的文件類型,這部分內容我們在前面的章節已經做了介紹,這里就不再贅述。如果要在/ e t c目錄下查找所有的目錄,可以用:
$ find /etc -type d -print
為了在當前目錄下查找除目錄以外的所有類型的文件,可以用:
$ find . ! -type d -print
為了在/ e t c目錄下查找所有的符號鏈接文件,可以用:
$ find /etc -type l -print
使用size選項
可以按照文件長度來查找文件,這里所指的文件長度既可以用塊( b l o c k)來計量,也可以用位元組來計量。以位元組計量文件長度的表達形式為N c;以塊計量文件長度只用數字表示即可。
就我個人而言,我總是使用以位元組計的方式,在按照文件長度查找文件時,大多數人都喜歡使用這種以位元組表示的文件長度,而不用塊的數目來表示,除非是在查看文件系統的大小,因為這時使用塊來計量更容易轉換。
為了在當前目錄下查找文件長度大於1 M位元組的文件,可以用:
$ find . -size +1000000c -print
為了在/ h o m e / a p a c h e目錄下查找文件長度恰好為1 0 0位元組的文件,可以用:
$ find /home/apache -size 100c -print
為了在當前目錄下查找長度超過1 0塊的文件(一塊等於5 1 2位元組),可以用:
$ find . -size +10 -print
使用depth選項
在使用f i n d命令時,可能希望先匹配所有的文件,再在子目錄中查找。使用d e p t h選項就
可以使f i n d命令這樣做。這樣做的一個原因就是,當在使用f i n d命令向磁帶上備份文件系統時,
希望首先備份所有的文件,其次再備份子目錄中的文件。
在下面的例子中, f i n d命令從文件系統的根目錄開始,查找一個名為C O N . F I L E的文件。
它將首先匹配所有的文件然後再進入子目錄中查找。
$ find / -name "CON.FILE" -depth -print
使用mount選項
在當前的文件系統中查找文件(不進入其他文件系統),可以使用f i n d命令的m o u n t選項。
在下面的例子中,我們從當前目錄開始查找位於本文件系統中文件名以X C結尾的文件:
$ find . -name "*.XC" -mount -print
使用cpio選項
c p i o命令可以用來向磁帶設備備份文件或從中恢復文件。可以使用f i n d命令在整個文件系
統中(更多的情況下是在部分文件系統中)查找文件,然後用c p i o命令將其備份到磁帶上。
如果希望使用c p i o命令備份/ e t c、/ h o m e和/ a p p s目錄中的文件,可以使用下面所給出的命令,不過要記住你是在文件系統的根目錄下:
(在上面的例子中,第一行末尾的\告訴s h e l l命令還未結束,忽略\後面的回車。)
在上面的例子中,應當注意到路徑中缺少/。這叫作相對路徑。之所以使用相對路徑,是因為在從磁帶中恢復這些文件的時候,可以選擇恢復文件的路徑。例如,可以將這些文件先恢復到另外一個目錄中,對它們進行某些操作後,再恢復到原始目錄中。如果在備份時使用了絕對路徑,例如/ e t c,那麼在恢復時,就只能恢復到/ e t c目錄中去,別無其他選擇。在上面的例子中,我告訴f i n d命令首先進入/ e t c目錄,然後是/ h o m e和/ a p p s目錄,先匹配這些目錄下的文件,然後再匹配其子目錄中的文件,所有這些結果將通過管道傳遞給c p i o命令進行備份。
順便說一下,在上面的例子中c p i o命令使用了C 6 5 5 3 6選項,我本可以使用B選項,不過這
樣每塊的大小隻有5 1 2 位元組,而使用了C 6 5 5 3 6 選項後,塊的大小變成了6 4 K 位元組
(6 5 5 3 6 / 1 0 2 4)。
使用exec或ok來執行shell命令
當匹配到一些文件以後,可能希望對其進行某些操作,這時就可以使用- e x e c選項。一旦f i n d命令匹配到了相應的文件,就可以用- e x e c選項中的命令對其進行操作(在有些操作系統中只允許- e x e c選項執行諸如l s或ls -l這樣的命令)。大多數用戶使用這一選項是為了查找舊文件並刪除它們。這里我強烈地建議你在真正執行r m命令刪除文件之前,最好先用l s命令看一下,確認它們是所要刪除的文件。
e x e c選項後面跟隨著所要執行的命令,然後是一對兒{ },一個空格和一個\,最後是一個分號。
為了使用e x e c選項,必須要同時使用p r i n t選項。如果驗證一下f i n d命令,會發現該命令只輸出從當前路徑起的相對路徑及文件名。
為了用ls -l命令列出所匹配到的文件,可以把ls -l命令放在f i n d命令的- e x e c選項中,例如:
上面的例子中,f i n d命令匹配到了當前目錄下的所有普通文件,並在- e x e c選項中使用ls -l
命令將它們列出。
為了在/ l o g s目錄中查找更改時間在5日以前的文件並刪除它們,可以用:
$ find logs -type f -mtime +5 -exec rm {} \;
記住,在s h e l l中用任何方式刪除文件之前,應當先查看相應的文件,一定要小心!
當使用諸如m v或r m命令時,可以使用- e x e c選項的安全模式。它將在對每個匹配到的文件進行操作之前提示你。在下面的例子中, f i n d命令在當前目錄中查找所有文件名以. L O G結尾、更改時間在5日以上的文件,並刪除它們,只不過在刪除之前先給出提示。
按y鍵刪除文件,按n鍵不刪除。
任何形式的命令都可以在- e x e c選項中使用。在下面的例子中我們使用g r e p命令。 首先匹配所有文件名為「 p a s s w d *」的文件,例如p a s s w d、p a s s w d . o l d、p a s s w d . b a k,然後執行g r e p命令看看在這些文件中是否存在一個r o u n d e r用戶。
find命令的例子
我們已經介紹了f i n d命令的基本選項,下面給出f i n d命令的一些其他的例子。
為了匹配$ H O M E目錄下的所有文件,下面兩種方法都可以使用:
$ find $HOME -print
$ find ~ -print
為了在當前目錄中查找s u i d置位,文件屬主具有讀、寫、執行許可權,並且文件所屬組的用
戶和其他用戶具有讀和執行的許可權的文件,可以用:
$ find . -type f -perm 4755 -print
為了查找系統中所有文件長度為0的普通文件,並列出它們的完整路徑,可以用:
$ find / -type f -size 0 -exec ls -l {} \;
為了查找/ v a r / l o g s目錄中更改時間在7日以前的普通文件,並刪除它們,可以用:
$ find /var/logs -type f -mtime +7 -exec rm {} \;
為了查找系統中所有屬於a u d i t組的文件,可以用:
$find /-name -group audit -print
我們的一個審計系統每天創建一個審計日誌文件。日誌文件名的最後含有數字,這樣我們一眼就可以看出哪個文件是最新的,哪個是最舊的。A d m i n . l o g 文件編上了序號:
a d m i n . l o g . 0 0 1、a d m i n . l o g . 0 0 2等等。下面的f i n d命令將刪除/ l o g s目錄中訪問時間在7日以前、含有數字後綴的a d m i n . l o g文件。該命令只檢查三位數字,所以相應日誌文件的後綴不要超過9 9 9。
$ find /logs -name 'admin.log[0-9][0-9]'[-0a-t9i]me +7 -exec rm {} \;
為了查找當前文件系統中的所有目錄並排序,可以用:
$ find . -type d -print -local -mount |sort
為了查找系統中所有的r m t磁帶設備,可以用:
$ find /dev/rmt -print
xargs
在使用f i n d命令的- e x e c選項處理匹配到的文件時, f i n d命令將所有匹配到的文件一起傳遞給e x e c執行。不幸的是,有些系統對能夠傳遞給e x e c的命令長度有限制,這樣在f i n d命令運行幾分鍾之後,就會出現溢出錯誤。錯誤信息通常是「參數列太長」或「參數列溢出」。這就是x a rg s命令的用處所在,特別是與f i n d命令一起使用。F i n d命令把匹配到的文件傳遞給x a rg s命令,而x a rg s命令每次只獲取一部分文件而不是全部,不像- e x e c選項那樣。這樣它可以先處理最先獲取的一部分文件,然後是下一批,並如此繼續下去。在有些系統中,使用- e x e c選項會為處理每一個匹配到的文件而發起一個相應的進程,並非將匹配到的文件全部作為參數一次執行;這樣在有些情況下就會出現進程過多,系統性能下降的問題,因而效率不高;而使用 a rg s命令則只有一個進程。另外,在使用x a rg s命令時,究竟是一次獲取所有的參數,還是分批取得參數,以及每一次獲取參數的數目都會根據該命令的選項及系統內核中相應的可調參數來確定。
讓我們來看看x a rg s命令是如何同f i n d命令一起使用的,並給出一些例子。
下面的例子查找系統中的每一個普通文件,然後使用x a rg s命令來測試它們分別屬於哪類
文件:
下面的例子在整個系統中查找內存信息轉儲文件(core mp) ,然後把結果保存到
/tmp/core.log 文件中:
$ find . -name "core" -print | xargs echo "" >/tmp/core.log
下面的例子在/ a p p s / a u d i t目錄下查找所有用戶具有讀、寫和執行許可權的文件,並收回相應的寫許可權:
$ find /apps/audit -perm -7 -print | xargs chmod o-w
在下面的例子中,我們用g r e p命令在所有的普通文件中搜索d e v i c e這個詞:
$ find / -type f -print | xargs grep "device"
在下面的例子中,我們用g r e p命令在當前目錄下的所有普通文件中搜索D B O這個詞:
$ find . -name *\-type f -print | xargs grep "DBO"
注意,在上面的例子中, \用來取消f i n d命令中的*在s h e l l中的特殊含義。
小結
f i n d命令是一個非常優秀的工具,它可以按照用戶指定的准則來匹配文件。使用e x e c和x a rg s可以使用戶對所匹配到的文件執行幾乎所有的命令。