UNIX find 命令的高階技術 (轉)

liuhaimiao發表於2014-11-20


沒有什麼能比得上探索和發現新的人、地方、事物所帶來的刺激。領域可能有所不同,但有些原則卻是一樣的。在這些原則中,有一條是記錄下您的旅程,另一條則是瞭解和使用工具。

UNIX? 作業系統很像一片廣闊的、未經標識的荒野。當您在這樣的領域中旅行時,可以選擇一些日後能夠給您帶來幫助的工具。find命令便是這樣一種工具。find 命令不僅能夠簡單地用來定位檔案,正如本文將介紹的那樣,它還可以自動地執行其他 UNIX 命令的序列,其中使用所查詢到的檔名作為輸入。

Find 的有關限制

所有稱職的作業系統都具有協助您查詢相關內容的工具。與大多數工具不同的是,UNIX 中的 find 命令可以自動地對其查詢到的檔案執行許多操作。

圖形使用者介面 (GUI) 中的標準 find 工具允許您對所查詢到的檔案進行一些常規操作任務:您可以將它們標記為剪下、複製和貼上,您可以將它們移動到一個新的位置,並且可以使用建立它們的應用程式來開啟它們。這些操作涉及到兩個或更多的步驟,並且不是自動完成的,即首先查詢到檔案,然後使用 GUI 為下一步的操作對它們進行標記。這種方法對許多使用者來說沒有問題,但是 Explorer 需要的不僅是這些。

UNIX 的 find 命令可以刪除、複製、移動和執行其查詢到的檔案。另外,使用 -exec 引數可以根據您所需要的 UNIX 命令的序列來自動地執行這些檔案。它甚至可以在對任何檔案執行這些操作前,進一步讓您進行確認。

簡化檔案系統的管理

與大多數 UNIX 命令一樣,UNIX find 命令具有一長串令人生畏的選項和開關,它們會阻礙人們深入地學習該命令,但正是因為其範圍廣闊,真正的 Explorer 並不會被它們嚇倒。一條好的通用原則在簡化一個複雜問題時都會經過漫長的過程。啟動一個 xterm,並嘗試執行下面的命令:

$ find . -name *.gif -exec ls {} \;

-exec 引數中包含了真正有價值的操作。當查詢到匹配搜尋條件的檔案時,-exec 引數定義了將對這些檔案進行什麼操作。該示例告訴計算機進行如下操作:

  1. 從當前資料夾開始往下搜尋,緊跟在 find 之後,使用點號 (.)。
  2. 定位所有名稱以 .gif 結尾的檔案(圖形檔案)。
  3. 列出所有查詢到的檔案,使用 ls 命令。

 

需要對 -exec 引數進行更深入地研究。當查詢到匹配搜尋條件的檔名時,find 命令執行 ls {} 字串,用檔名和路徑代替文字{}。假設在搜尋中查詢到 saturn.gif 檔案,find 將執行如下所示的命令:

$ ls ./gif_files/space/solar_system/saturn.gif

本文餘下的內容建立在這條一般原則之上:仔細地使用 find 命令可以讓 UNIX 檔案系統的管理工作變得更加容易。例如,如果您使用了 -fstype 引數,find 命令可以根據查詢到的檔案所處的檔案系統的型別來對命令進行相應的處理。在 find 命令對查詢到的檔案執行相應命令前將對您進行提示,這通常是非常有用的,您可以使用 -ok 引數告訴它繼續執行該操作,接下來我們將對其進行介紹。

可選的執行

-ok 是 -exec 引數的一個重要的替代項,它的行為和 -exec 一樣,但它會提示您是否要對檔案執行相應的命令。假設您想要刪除 home 目錄中的大部分 .txt 檔案,但希望能夠逐個檔案地執行該操作。像 UNIX 中的 rm 命令那樣的刪除操作是很危險的,因為當使用像 find 這樣的自動化處理方式來查詢檔案時,它可能一不小心會刪除重要的檔案,您也許希望在刪除這些系統查詢到的檔案之前對其進行仔細檢查。

下面的命令列出了您的 home 目錄中所有的 .txt 檔案。要刪除這些檔案,必須在 find 命令透過列出檔名提示您確認操作時輸入 Y 或者 y:

$ find $HOME/. -name *.txt -ok rm {} \;

它列出了查詢到的每個檔案,並且系統將暫停以等待您輸入 Y 或者 y。如果您按下 Enter 鍵,系統將不會刪除該檔案。清單 1 顯示了一些示例結果:


清單 1. 示例結果
< 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 > ?
.
.
.

系統將在每個問號之後暫停,在本示例中,每次都按下了 Enter 鍵以繼續處理下一個檔案。(沒有刪除任何檔案。)-ok 引數允許您控制每個查詢到的檔案的自動化處理過程,這樣就新增了一種避免自動刪除檔案的安全措施。

如果在使用 -ok 引數時涉及到過多的檔案,那麼一個好的方法是先執行帶 -exec 的 find 命令以列出所有將要刪除的檔案,然後在經過檢查確保其中不會刪除重要的檔案後,再次執行該命令,其中用 rm 代替 ls。

-exec 和 -ok 都非常有用,您必須確定在當前情況下哪一個能夠更好的工作。請記住,安全第一!

創造性地使用 find

您可以使用 find 命令執行各種各樣的任務。本部分內容提供了使用 find 命令來管理檔案系統的幾種方式的示例。

為了保持簡單,這些示例都避免了使用涉及透過管道將一個命令的輸出傳遞到另一個命令的 -exec 命令。然而,您完全可以根據自己需要在 find 命令的 -exec 子句中使用這樣的命令。

清除臨時檔案

您可以使用 find 命令來清除目錄或子目錄中在正常使用過程中生成的臨時檔案,這樣可以節省磁碟空間。要實現該操作,請使用下面的命令:

$ find . \( -name a.out -o -name '*.o' -o -name 'core' \) -exec rm {} \;

括號中的檔案掩碼 標識出了需要刪除的檔案型別,每個檔案掩碼的前面都有 -name。該列表可以擴充套件為包括您需要清除的系統中的任何臨時檔案型別。在程式碼的編譯和連線過程中,程式設計師及其工具會生成示例中的那些檔案型別:a.out、*.o 和 core。其他的使用者通常也會生成類似的臨時檔案,可以使用如 *.tmp、*.junk 等檔案掩碼來對命令進行相應的編輯。您可能還發現將命令放入一個稱作clean 的指令碼中非常有用,當需要清除一個目錄中的內容的時候就可以執行該指令碼。

複製目錄中的內容

find 命令允許您複製目錄中的全部內容,同時保持每個檔案和子目錄的許可權、時間和所有權。要完成該操作,需要組合使用 find 和cpio 命令,如下所示:


清單 2. 組合使用 find 和 cpio 命令
$ cd /path/to/source/dir

$ find . | cpio -pdumv /path/to/destination/dir

cpio 命令是一個複製命令,它設計用來將檔案複製到或複製出一個 cpio 或 tar 存檔檔案,並自動地保持檔案和子目錄的許可權、時間和所有權。

列出文字檔案的第一行內容

有些人使用每個文字檔案的第一行作為標題或者檔案內容的描述。可以使用列出檔名和所有文字檔案第一行內容的報表更方便地對大量的文字檔案進行篩選。下面的命令在報表中列出了您的 home 目錄中所有文字檔案的第一行內容,便於進一步地根據需要使用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 小時內 (-mtime +0) 進行了修改的資料的目錄 (-type d),並對它們進行壓縮 (compress -r {}) 以節省磁碟空間。如果這些目錄超過了一個工作周 (-mtime +5),第二個命令則將其刪除 (rm -f {}),以便增加磁碟上的可用空間。透過這種方式,cron 任務自動地根據您所指定的時間視窗對目錄進行維護。

複製複雜的目錄樹

如果您想要將複雜的目錄樹從一臺計算機複製到另一臺計算機,同時保持副本許可權以及 User ID 和 Group ID(UID 和 GID——作業系統所使用的標記檔案的所有權的數值),並且不復制使用者檔案,那麼就需要再次使用 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 可以在大多數的 UNIX 工具包中找到,它是許多功能強大的解釋性語言工具中的一種。

定位和重新命名無法列印的目錄

在 UNIX 中,可能會有錯誤的或惡意的程式建立包含無法列印的字元的目錄。定位和重新命名這些目錄,這樣就可以更容易地檢查並刪除它們。要完成該操作,您首先需要在 ls 中包含 -i 開關,以獲取該目錄的索引節點的數值。然後,使用 find 將索引節點的數值轉換為一個可以使用 mv 命令進行重新命名的檔名:


清單 6. 定位和重新命名無法列印的目錄
$ ls -ail

$ find . -inum 211028 -exec mv {} newname.dir \;

列出長度為零的檔案

要列出所有長度為零的檔案,請使用下面的命令:

$ find . -empty -exec ls {} \;

在查詢到空檔案之後,您可以選擇用 rm 命令來代替 ls 命令,以刪除這些檔案。

很明顯,您對 UNIX find 命令的使用受到知識和創造性的限制。

結束語

使用 find 命令,可以輕鬆地瀏覽 UNIX 檔案系統中豐富的內容。很值得花時間來試驗該命令,並瞭解它能為您做些什麼。正如本文中所列出的示例,您可以透過許多創造性的方式來使用 find,這樣可以輕鬆地瀏覽和管理檔案系統,並且充滿樂趣。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/223653/viewspace-1340034/,如需轉載,請註明出處,否則將追究法律責任。

相關文章