[轉貼] 如何在 Linux 底下找到想找的東西?

以下為從 自由軟體鑄造場 全文轉貼之文章,同時感念該網站對於台灣自由軟體與開源專案的貢獻。

作者是 Carla Schroder / 文,蕭惟杰(RJ Hsiao)/ 翻譯

◎ 本文翻譯自 OLEX Wazi,採 Creative Commons Attribution 3.0 Unported 授權釋出。

在 Linux 底下,"find"、"grep" 及 “awk" 是精細且強大的檔案搜尋工具。透過它們,你可以找到系統上最大和最新的文件、微調搜索參數、搜尋文件內的文字,並執行一些華麗的用戶管理技巧。

 

搜尋最大或最新的檔案

只要你能弄清楚的話,"find" 指令幾乎可以做到任何事。下面的例子是一個能從小到大排序系統中十個最佔空間的檔案,並以人性化方便閱讀的格式顯示容量大小的範例:

# find / -type f -exec du {} \; 2>/dev/null | sort -n | tail -n 10 | xargs -n 1 du -h 2>/dev/null  
1.2G/home/carla/.local/share/Trash/files/download  
1.3G/home/carla/sda1/carla/.VirtualBox/Machines/ubuntu-hoary/Snapshots/{671041dd-700c-4506-68a8-7edfcd0e3c58}.vdi  
2.2G/home/carla/.local/share/Trash/files/dreamstudio.iso  
[...]

這些結果提醒了我為什麼我不喜歡有個資源回收筒,因為當我刪除某些檔案的時候,我是十分認真的確定要刪除(但是檔案仍存在在資源回收筒中)。這個指令會強制搜尋整個檔案系統而且跑一次大概需要幾分鐘才會跑完,所以你可以趁機去外面走一走運動身體。當然,你可以修改指令來搜尋指定的資料夾;舉例來說,用 “find /var/" 來尋找肥大的日誌檔案。

進一步了解這個指令將會發現 “find / -type f" 的意思是「搜尋根目錄中的所有檔案」。選項 “-exec" 是指加入其他指令,然而在這個範例中,加入的是 “du" 這個查詢磁碟使用量的 “-exec du {} \;" 代表「每個找到的檔案都用 du 指令執行以取得以 bytes 為單位的檔案大小資訊」。"2>/dev/null" 是指將所有的錯誤訊息丟棄,使它們不會干擾你的結果。如果你還是想查看被丟棄的訊息的話,可以將範例指令中的兩個 “2>/dev/null" 都刪掉並重新執行。"sort -n" 會將所有的檔案依大小列出,而 “tail -n 10″ 則是顯示最後 10 筆,兩個指令合起來就會顯示出依大小排序的前 10 大檔案。你可以把指令打到這裡就執行,然後可以看到像下面那樣的輸出:

1206316 /home/carla/.local/share/Trash/files/download
2209784 /home/carla/.local/share/Trash/files/dreamstudio.iso

“xargs -n 1 du -h" 用來做最後的修飾,將檔案大小從以 bytes 為單位轉成比較好讀的格式。

你可以輕鬆的尋找電腦中最後 5 分鐘內變動過的所有檔案:

# find / -mmin -5 -type f

下面的指令則用來找尋在最後 10 到 20 分鐘之間變動過的檔案:

# find / -mmin +10 -mmin -20 -type f

“+10″ 指的是 10 分鐘以前,而 “-20″ 指最後 20 分鐘內。如果你不使用加號或減號,則表示恰好為那個數字。另外,也可以使用 “-mtime" 來以 n 天=n*24 小時為單位進行搜尋。如果你想找的是資料夾,則用 “-type d"。

 

在多個資料夾內搜尋

如下面範例所示,你可以列出任意多個要搜尋的資料夾:

# find /etc /var /mnt /media -xdev -mmin -5 -type f

“-dev" 限制在所在的檔案系統內進行搜尋,而不會跨過其他掛載的檔案系統。"find" 預設不會隨著符號連結做深入搜尋,所以你只需要加入 “-dev" 使得搜尋侷限於指定的檔案系統而不會隨著網路共享空間及可移除裝置到處流浪。

 

排除指定目錄

你可以利用 “prune" 選項來排除指定目錄來達到縮小搜尋範圍的效果。"prune" 這個選項有點奇怪:你必須反向思考。下面的例子將會搜尋除了 /proc 及 /sys 這兩個虛擬目錄以外的整個檔案系統:

# find /etc /var /mnt /media -xdev -mmin -5 -type f

首先,你要列出要被排除的目錄,"-o" 表示 “or",然後記得要替括號加上溢出字元(反斜線)。然後,"-prune -o" 表示「不要去查看前面列出的目錄」。

我喜歡利用 “prune" 選項來排除瀏覽器的暫存檔,因為這些檔案會混淆搜尋結果。下面的例子將能達到我前述的需求,並列出每個檔案的日期時間:

$ find / \( -name proc -o -name sys -o -name .mozilla -o -name chromium \) -prune -o -type f -mmin -10 -printf "%Ac\t%p\n"
Wed 28 Sep 2011 10:34:54 AM PDT /home/carla/.local/share/akonadi/db_data/ib_logfile0
Wed 28 Sep 2011 10:34:54 AM PDT /home/carla/.local/share/akonadi/db_data/ibdata1
Wed 28 Sep 2011 05:21:48 PM PDT /home/carla/articles/findgrep.html

其中 “printf" 這個選項代表「輸出格式」。當你想控制你的輸出格式時,請善用 “printf"。你可以指定斷行,日期與時間的格式,以及檔案屬性像是權限、所有者及時間戳記。加入 “%Ac" 將會輸出日期與時間,"\t" 則是跳到下一個定位點,"%p" 則會印出完整的檔案名稱,而 “\n" 則是加入斷行標記。

如你所見,"find" 有許多使用者經常透過 “ls" 指令來完成工作的內建功能。

 

搜尋特定類型的檔案

利用檔案副檔名來搜尋是非常容易的。下列的例子將會在目前的目錄下搜尋三種不同的圖片格式:

$ find . -name "*.png" -o -name "*.jpg" -o -name "*.gif" -type f

利用 “-name" 舉例來說,想搜尋 *mysong.ogg*,你可以用檔名的任何一部分搭配一般 shell 的萬用字元,像 “mys*" 使用 “-iname" 來進行不區分大小寫的搜尋。

 

搜尋重複檔案

這邊介紹兩種可以搜尋重複檔案的方法。第一個方法透過下列指令來檢查檔案的 MD5 切細值 (hash):

$ find . -type f -exec md5sum '{}' ';' | sort | uniq --all-repeated=separate -w 24

上述指令將會計算每個檔案的 MD5 切細值並藉此加以排序,分開顯示在不同的行上,並比對每個切細值的前 24 位數。

第二種方法則是檢查檔案大小:

$ find . -type f -printf "%p - %s\n" | sort -nr -k3 | uniq -D -f1

兩種方法各有優缺,比對 MD5 切細值會得到非常精準的結果,可是比對檔案大小則速度比較快。

 

搜尋檔案內的文字

若要在文字檔案裡面找東西,"grep" 這個指令可以說是超級無敵好用的。假設你有一個資料夾放了滿滿的伺服器設定檔,而你想要在這些檔案之中搜尋你所有的測試項目。如果你很有先見之明的對那些測試項目都使用了 “test" 這個字,下面的指令可以幫你找到它們:

# grep -inR -A2 test /etc/fooserver/

這個指令告訴 “grep" 以不區分大小寫及遞迴(遇到目錄則繼續搜尋目錄內的檔案)的方式在 /etc/fooserver/ 目錄下搜尋,並印出吻合條件的那一行及下兩行。"n" 選項表示印出行號,這對於大檔案來說是十分有用的。

 

搜尋文字區塊

“awk" 這個指令能夠進行 “grep" 不能做到的搜尋相關文字區塊的功能,透過一個簡單的語法:awk ‘/開始樣式/,/結束樣式/’。假設你想透過 “lspci" 指令來查看關於 Ethernet 裝置的擴展訊息:

$ lspci -v | awk '/[Ee]thernet/,/^$/
08:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168B PCI Express Gigabit Ethernet controller (rev 03)
Subsystem: Lenovo Device 2131
Flags: bus master, fast devsel, latency 0, IRQ 46
I/O ports at 3000 [size=256]
Memory at f2004000 (64-bit, prefetchable) [size=4K]
Memory at f2000000 (64-bit, prefetchable) [size=16K]
[virtual] Expansion ROM at f2020000 [disabled] [size=128K]
Capabilities:
Kernel driver in use: r8169
Kernel modules: r8169

你必須知道你所想看區塊的起始及結束,因此這是一個能夠將設定檔的一部分迅速抽出來看的偉大工具。

下面的例子展現出用花括號做區塊分隔的優勢,並在 radiusd.conf 中迅速找到 “listen" 項目:

# awk '/listen {/,/}/' /etc/freeradius/radiusd.conf
listen {
ipaddr = *
# ipv6addr = ::
port = 0
type = acct
# interface = eth0
# clients = per_socket_clients
}

 

管理使用者及檔案

員工離職,造成組織裡系統檔案的檔案擁有者及權限搞得一團糟,"find" 可以幫你迅速搞定這一切。你可以找到屬於特定使用者的所有檔案:

# find / -user carla

或是特定群組

# find / -group admins

你也可以透過 “-uid" 及 “-gid" 選項來搜尋指定的 UID 及 GID。然後你可以利用使用者名稱或是 UID 將這使用者的所有檔案移交擁有者權限給另一個使用者:

# find / -uid 1100 -ok chown -v 1200 {} \;
# find / -user carla -ok chown -v steven {} \;

當然也可以用來改變檔案的所屬群組:

# find / -group carla -ok chgrp -v admins {} \;

使用 “-ok" 選項來要求你必須對所有的變動做確認。如果你對你做的變動有信心,那麼也可以改用 “-exec"。

當員工離職,可能需要遵守政策來移除他們的檔案,而使用 “find" 可以輕鬆完成:

# find / -user 1100 -exec rm {} \;

當然你必須非常確定你有權這樣做,因為 “find" 不會嘮叨的問你確不卻定要刪除。它只會單純的執行你下達的指令。

“find"、"grep"及"awk"-讀者可以透過這篇文章中所提到的用法,以及參考它們的使用手冊中所給予的些許提示,如此一來,在 Linux 系統上找尋任何檔案就會變得非常容易。

 

 

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *


+ 八 = 16

你可以使用這些 HTML 標籤與屬性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>