使用 UNIX find 命令的高級技術(shù)
沒有什么能比得上探索和發(fā)現(xiàn)新的人、地方、事物所帶來的刺激。領域可能有所不同,但有些原則卻是一樣的。在這些原則中,有一條是記錄下您的旅程,另一條則是了解和使用工具。
Unix® 操作系統(tǒng)很像一片廣闊的、未經(jīng)標識的荒野。當您在這樣的領域中旅行時,可以選擇一些日后能夠給您帶來幫助的工具。find 命令便是這樣一種工具。find 命令不僅能夠簡單地用來定位文件,正如本文將介紹的那樣,它還可以自動地執(zhí)行其他 UNIX 命令的序列,其中使用所查找到的文件名作為輸入。
Find 的有關限制
所有稱職的操作系統(tǒng)都具有協(xié)助您查找相關內(nèi)容的工具。與大多數(shù)工具不同的是,UNIX 中的 find 命令可以自動地對其查找到的文件執(zhí)行許多操作。
圖形用戶界面 (GUI) 中的標準 find 工具允許您對所查找到的文件進行一些常規(guī)操作任務:您可以將它們標記為剪切、復制和粘貼,您可以將它們移動到一個新的位置,并且可以使用創(chuàng)建它們的應用程序來打開它們。這些操作涉及到兩個或更多的步驟,并且不是自動完成的,即首先查找到文件,然后使用 GUI 為下一步的操作對它們進行標記。這種方法對許多用戶來說沒有問題,但是 Explorer 需要的不僅是這些。
UNIX 的 find 命令可以刪除、復制、移動和執(zhí)行其查找到的文件。另外,使用 -exec 參數(shù)可以根據(jù)您所需要的 UNIX 命令的序列來自動地運行這些文件。它甚至可以在對任何文件執(zhí)行這些操作前,進一步讓您進行確認。
簡化文件系統(tǒng)的管理
與大多數(shù) UNIX 命令一樣,UNIX find 命令具有一長串令人生畏的選項和開關,它們會阻礙人們深入地學習該命令,但正是因為其范圍廣闊,真正的 Explorer 并不會被它們嚇倒。一條好的通用原則在簡化一個復雜問題時都會經(jīng)過漫長的過程。啟動一個 xterm,并嘗試執(zhí)行下面的命令:
$ find . -name *.gif -exec ls {} ;
-exec 參數(shù)中包含了真正有價值的操作。當查找到匹配搜索條件的文件時,-exec 參數(shù)定義了將對這些文件進行什么操作。該示例告訴計算機進行如下操作:
從當前文件夾開始往下搜索,緊跟在 find 之后,使用點號 (.)。
定位所有名稱以 .gif 結(jié)尾的文件(圖形文件)。
列出所有查找到的文件,使用 ls 命令。
需要對 -exec 參數(shù)進行更深入地研究。當查找到匹配搜索條件的文件名時,find 命令執(zhí)行 ls {} 字符串,用文件名和路徑代替文本 {}。假設在搜索中查找到 saturn.gif 文件,find 將執(zhí)行如下所示的命令:
$ ls ./gif_files/space/solar_system/saturn.gif
本文余下的內(nèi)容建立在這條一般原則之上:仔細地使用 find 命令可以讓 Unix 文件系統(tǒng)的管理工作變得更加容易。例如,如果您使用了 -fstype 參數(shù),find 命令可以根據(jù)查找到的文件所處的文件系統(tǒng)的類型來對命令進行相應的處理。在 find 命令對查找到的文件執(zhí)行相應命令前將對您進行提示,這通常是非常有用的,您可以使用 -ok 參數(shù)告訴它繼續(xù)執(zhí)行該操作,接下來我們將對其進行介紹。
可選的執(zhí)行
-ok 是 -exec 參數(shù)的一個重要的替代項,它的行為和 -exec 一樣,但它會提示您是否要對文件運行相應的命令。假設您想要刪除 home 目錄中的大部分 .txt 文件,但希望能夠逐個文件地執(zhí)行該操作。像 UNIX 中的 rm 命令那樣的刪除操作是很危險的,因為當使用像 find 這樣的自動化處理方式來查找文件時,它可能一不小心會刪除重要的文件,您也許希望在刪除這些系統(tǒng)查找到的文件之前對其進行仔細檢查。
下面的命令列出了您的 home 目錄中所有的 .txt 文件。要刪除這些文件,必須在 find 命令通過列出文件名提示您確認操作時輸入 Y 或者 y:
$ find $HOME/. -name *.txt -ok rm {} ;
它列出了查找到的每個文件,并且系統(tǒng)將暫停以等待您輸入 Y 或者 y。如果您按下 Enter 鍵,系統(tǒng)將不會刪除該文件。清單 1 顯示了一些示例結(jié)果:
清單 1. 示例結(jié)果
< rm ... /home/bill/./.kde/share/apps/karm/karmdata.txt > ?< rm ... /home/bill/./archives/LDDS.txt > ?< rm ... /home/bill/./www/txt/textfile1.txt > ?< rm ... /home/bill/./www/txt/faq.txt > ?< rm ... /home/bill/./www/programs/MIKE.txt > ?< rm ... /home/bill/./www/programs/EESTRING.txt > ?...
系統(tǒng)將在每個問號之后暫停,在本示例中,每次都按下了 Enter 鍵以繼續(xù)處理下一個文件。(沒有刪除任何文件。)-ok 參數(shù)允許您控制每個查找到的文件的自動化處理過程,這樣就添加了一種避免自動刪除文件的安全措施。
如果在使用 -ok 參數(shù)時涉及到過多的文件,那么一個好的方法是先運行帶 -exec 的 find 命令以列出所有將要刪除的文件,然后在經(jīng)過檢查確保其中不會刪除重要的文件后,再次運行該命令,其中用 rm 代替 ls。
-exec 和 -ok 都非常有用,您必須確定在當前情況下哪一個能夠更好的工作。請記住,安全第一!
創(chuàng)造性地使用 find
您可以使用 find 命令執(zhí)行各種各樣的任務。本部分內(nèi)容提供了使用 find 命令來管理文件系統(tǒng)的幾種方式的示例。
為了保持簡單,這些示例都避免了使用涉及通過管道將一個命令的輸出傳遞到另一個命令的 -exec 命令。然而,您完全可以根據(jù)自己需要在 find 命令的 -exec 子句中使用這樣的命令。
清除臨時文件
您可以使用 find 命令來清除目錄或子目錄中在正常使用過程中生成的臨時文件,這樣可以節(jié)省磁盤空間。要實現(xiàn)該操作,請使用下面的命令:
$ find . ( -name a.out -o -name '*.o' -o -name 'core' ) -exec rm {} ;
括號中的文件掩碼 標識出了需要刪除的文件類型,每個文件掩碼的前面都有 -name。該列表可以擴展為包括您需要清除的系統(tǒng)中的任何臨時文件類型。在代碼的編譯和連接過程中,程序員及其工具會生成示例中的那些文件類型:a.out、*.o 和 core。其他的用戶通常也會生成類似的臨時文件,可以使用如 *.tmp、*.junk 等文件掩碼來對命令進行相應的編輯。您可能還發(fā)現(xiàn)將命令放入一個稱作 clean 的腳本中非常有用,當需要清除一個目錄中的內(nèi)容的時候就可以執(zhí)行該腳本。
復制目錄中的內(nèi)容
find 命令允許您復制目錄中的全部內(nèi)容,同時保持每個文件和子目錄的權(quán)限、時間和所有權(quán)。要完成該操作,需要組合使用 find 和 cpio 命令,如下所示:
清單 2. 組合使用 find 和 cpio 命令
$ cd /path/to/source/dir$ find . | cpio -pdumv /path/to/destination/dir
cpio 命令是一個復制命令,它設計用來將文件復制到或復制出一個 cpio 或 tar 存檔文件,并自動地保持文件和子目錄的權(quán)限、時間和所有權(quán)。
列出文本文件的第一行內(nèi)容
有些人使用每個文本文件的第一行作為標題或者文件內(nèi)容的描述。可以使用列出文件名和所有文本文件第一行內(nèi)容的報表更方便地對大量的文本文件進行篩選。下面的命令在報表中列出了您的 home 目錄中所有文本文件的第一行內(nèi)容,便于進一步地根據(jù)需要使用 less 命令進行檢查:
清單 3. less 命令
$ find $HOME/. -name *.txt -exec head -n 1 -v {} ; > report.txt$ less < report.txt
維護 LOG 和 TMP 文件的存儲空間
要為生成大量文件的應用程序維護 LOG 和 TMP 文件存儲空間,可以將下列命令放入到每天運行的 cron 任務中:
清單 4. 維護 LOG 和 TMP 文件存儲空間
$ find $LOGDIR -type d -mtime +0 -exec compress -r {} ;$ find $LOGDIR -type d -mtime +5 -exec rm -f {} ;
第一個命令找到 $LOGDIR 目錄中所有包含在 24 小時內(nèi) (-mtime +0) 進行了修改的數(shù)據(jù)的目錄 (-type d),并對它們進行壓縮 (compress -r {}) 以節(jié)省磁盤空間。如果這些目錄超過了一個工作周 (-mtime +5),第二個命令則將其刪除 (rm -f {}),以便增加磁盤上的可用空間。通過這種方式,cron 任務自動地根據(jù)您所指定的時間窗口對目錄進行維護。
復制復雜的目錄樹
如果您想要將復雜的目錄樹從一臺計算機復制到另一臺計算機,同時保持副本權(quán)限以及 User ID 和 Group ID(UID 和 GID——操作系統(tǒng)所使用的標記文件的所有權(quán)的數(shù)值),并且不復制用戶文件,那么就需要再次使用 find 和 cpio:
清單 5. 復制復雜的目錄樹
$ cd /source/Directory$ find . -depth -print | cpio -o -O /target/directory
查找不指向任何地方的鏈接
要查找不指向任何地方的鏈接,可以使用帶 find 的 perl 解釋器,如下所示:
$ find / -type l -print | perl -nle '-e || print';
該命令從最頂層目錄 (/) 開始,列出由 perl 解釋器確定不指向任何地方 (-nle '-e || print') 的所有鏈接 (-type l -print),關于 Unix Guru Universe 站點中這個技巧的更詳細的信息,請參閱參考資料部分。如果您想要刪除這些文件,可以進一步使用管道將輸出傳遞到 rm -f {} 命令。當然,Perl 可以在大多數(shù)的 UNIX 工具包中找到,它是許多功能強大的解釋性語言工具中的一種。
定位和重命名無法打印的目錄
在 UNIX 中,可能會有錯誤的或惡意的程序創(chuàng)建包含無法打印的字符的目錄。定位和重命名這些目錄,這樣就可以更容易地檢查并刪除它們。要完成該操作,您首先需要在 ls 中包含 -i 開關,以獲取該目錄的索引節(jié)點的數(shù)值。然后,使用 find 將索引節(jié)點的數(shù)值轉(zhuǎn)換為一個可以使用 mv 命令進行重命名的文件名:
清單 6. 定位和重命名無法打印的目錄
$ ls -ail$ find . -inum 211028 -exec mv {} newname.dir ;
列出長度為零的文件
要列出所有長度為零的文件,請使用下面的命令:
$ find . -empty -exec ls {} ;
在查找到空文件之后,您可以選擇用 rm 命令來代替 ls 命令,以刪除這些文件。
很明顯,您對 UNIX find 命令的使用受到知識和創(chuàng)造性的限制。
結(jié)束語
使用 find 命令,可以輕松地瀏覽 UNIX 文件系統(tǒng)中豐富的內(nèi)容。很值得花時間來試驗該命令,并了解它能為您做些什么。正如本文中所列出的示例,您可以通過許多創(chuàng)造性的方式來使用 find,這樣可以輕松地瀏覽和管理文件系統(tǒng),并且充滿樂趣。
