前言
find 是 Linux 最強大、最靈活的檔案搜尋工具,支援檔名、類型、大小、時間、權限、擁有者、內容、深度、動作執行等多維度條件組合。掌握 find 等於掌握了檔案系統的精準手術刀。本文系統整理語法結構、核心選項、實戰範例、效能優化與常見陷阱。
一、基本語法結構
find [搜尋路徑...] [運算式]
# 運算式 = 選項 + 測試條件 + 動作
# 預設動作:-print
# 邏輯運算子:-a (AND, 預設) -o (OR) ! (NOT) ( ) 分組
二、核心測試條件速查表
| 類別 | 選項 | 說明 | 範例 |
| 名稱 | -name pattern | 檔名匹配(大小寫敏感,支援 * ? []) | -name "*.log" |
-iname pattern | 檔名匹配(大小寫不敏感) | -iname "readme*" |
-path pattern | 完整路徑匹配 | -path "*/cache/*" |
-ipath pattern | 完整路徑匹配(不敏感) | -ipath "*/tmp/*" |
-regex pattern | 正則表達式匹配完整路徑 | -regex ".*/[0-9]+\.log" |
-lname pattern | 符號連結目標匹配 | -lname "/usr/*" |
| 類型 | -type f | 一般檔案 | -type f |
-type d | 目錄 | -type d |
-type l | 符號連結 | -type l |
-type b/c/p/s | 區塊/字元裝置/管道/Socket | -type s |
-xtype | 針對符號連結目標類型 | -xtype f |
| 大小 | -size n[cwbkMG] | n 單位:c=Bytes, w=2Bytes, b=512Bytes(預設), k=KiB, M=MiB, G=GiB | -size +100M (大於100MiB) |
-empty | 空檔案或空目錄 | -empty |
| 時間 | -atime n | 存取時間 n*24小時前(+n 超過,-n 內,n 正好) | -atime -7 (7天內存取過) |
-mtime n | 修改時間(內容變更) | -mtime +30 (30天前修改) |
-ctime n | 狀態改變時間(inode 變更:權限、擁有者、連結數) | -ctime -1 |
-amin/-mmin/-cmin n | 分鐘級精度 | -mmin -60 (1小時內修改) |
-newer file | 比參考檔案新(修改時間) | -newer /etc/passwd |
-anewer/-cnewer | 存取/狀態比參考檔新 | -cnewer /etc/shadow |
| 權限/擁有者 | -perm mode | 權限精確匹配(八進位) | -perm 644 |
-perm -mode | 至少包含指定權限位 | -perm -u=x (擁有者可執行) |
-perm /mode | 任一權限位匹配 | -perm /u=w,g=w |
-user name/uid | 擁有者 | -user www |
-group name/gid | 群組 | -group www |
| 深度控制 | -maxdepth n | 最大遞迴深度(0=僅當前目錄) | -maxdepth 2 |
-mindepth n | 最小深度 | -mindepth 1 |
-mount / -xdev | 不跨越檔案系統邊界 | -mount |
三、動作選項
| 動作 | 說明 | 範例 |
-print | 輸出路徑(預設,換行分隔) | -print |
-print0 | 輸出路徑(NUL 分隔,配合 xargs -0) | -print0 | xargs -0 rm |
-printf format | 格式化輸出(如 %p %s %TY-%Tm-%Td %TH:%TM) | -printf "%p %s\n" |
-ls | 類似 ls -dils 詳細資訊 | -ls |
-delete | 刪除檔案(深度優先,比 exec rm 安全快速) | -delete |
-exec cmd {} + | 執行命令,{} 替換路徑,+ 批次傳遞(少啟動進程) | -exec chmod 644 {} + |
-exec cmd {} \; | 執行命令,每檔案啟動一次進程 | -exec rm {} \; |
-ok cmd {} \; | 互動式確認後執行 | -ok rm {} \; |
四、實戰黃金範例
1. 找出超過 100MB 的日誌檔並壓縮
find /var/log -type f -name "*.log" -size +100M -exec gzip {} +
2. 清理 30 天前的暫存檔(含子目錄)
find /tmp -type f -mtime +30 -delete
# 或互動確認
find /tmp -type f -mtime +30 -ok rm {} \;
3. 找出擁有者為 user1 且權限包含群組寫入的檔案
find /home -user user1 -perm /g=w -ls
4. 尋找最近 1 小時內被修改過的設定檔
find /etc -type f \( -name "*.conf" -o -name "*.ini" -o -name "*.yaml" \) -mmin -60
5. 找出斷開的符號連結
find /usr -xtype l -ls
# 或
find /usr -type l ! -exec test -e {} \; -print
6. 統計專案中程式碼行數(排除 .git、build、vendor)
find . -type f \( -name "*.c" -o -name "*.h" -o -name "*.cpp" -o -name "*.hpp" \) \
-not -path "*/.git/*" -not -path "*/build/*" -not -path "*/vendor/*" \
-exec wc -l {} + | tail -1
7. 批次重命名:將空白替換為底線
find . -depth -name "* *" -execdir bash -c 'mv "$1" "${1// /_}"' _ {} \;
8. 找出佔用空間最大的前 20 個檔案
find / -type f -size +100M -printf "%s %p\n" 2>/dev/null | sort -rn | head -20
五、效能優化與避坑指南
| 問題 | 原因 | 解決 |
| 遍歷極慢 | 掃描整個 /、跨網路檔案系統、遇大量小檔目錄 | 限定路徑、加 -mount、用 -maxdepth、避開 /proc /sys /run |
| 引數過長 | -exec cmd {} \; 每檔啟動進程 | 改用 -exec cmd {} + 批次傳遞 |
| 檔名含空白/換行導致 xargs 錯誤 | 預設以空白分隔 | -print0 | xargs -0 |
| 刪除目錄失敗 | -delete 不刪非空目錄 | -exec rm -rf {} + 或 rmdir 先清空 |
| 權限拒絕錯誤訊息汙染輸出 | 無讀取權限目錄 | 2>/dev/null 或 -readable 先過濾 |
六、locate / mlocate / plocate:極速替代方案
- 原理:預建索引資料庫(
/var/lib/mlocate/mlocate.db),每日 updatedb 更新。
- 指令:
locate pattern(毫秒級回應)。
- 缺點:非即時、需權限可見、不支援複雜條件(大小、時間、權限)。
- 現代替代:
plocate(基於 posting lists,索引更小、查詢更快)。
七、總結
find 的威力在於條件組合(-a/-o/!)、深度控制、動作批次執行({} +)、NUL 安全輸出(-print0)。背誦「名稱/類型/大小/時間/權限/深度」六大維度核心選項,配合 -exec ... + 與 xargs -0,即可解決 99% 檔案搜尋與批次處理需求。