find 是 Linux 最強大的檔案搜尋工具,支援依名稱、類型、大小、時間、權限、擁有者等多維度條件組合,並可對結果執行任意命令。本文系統講解 find 語法核心、常用選項、條件邏輯組合、深度控制、類型過濾、-exec/xargs 批次處理與實戰場景範例。
基本語法
find [路徑...] [運算式/條件...] [動作...]
# 路徑預設為當前目錄 .
# 條件隱含 AND 邏輯,需顯式用 -o (OR)、! (NOT)、\( \) 分組
核心條件選項速查表
| 類別 | 選項 | 說明 | 範例 |
| 名稱/路徑 | -name 模式 | 檔案名匹配 (區分大小寫),支援通配符 * ? [] | -name "*.log" |
-iname 模式 | 不區分大小寫 | -iname "readme*" |
-path 模式 | 完整路徑匹配 | -path "*/cache/*" |
-ipath 模式 | 路徑不區分大小寫 | |
-regex 模式 | 正則表達式匹配完整路徑 | -regex ".*\.tmp$" |
| 時間 (天為單位) | -mtime n | 修改時間 n 天前 (n=0 今天,n=1 昨天,n=-1 1天內) | -mtime +7 (超過 7 天) |
-atime n | 存取時間 | |
-ctime n | 狀態改變時間 (inode 變更) | |
| 時間 (分鐘單位) | -mmin n | 修改時間 n 分鐘前 | -mmin -60 (1小時內) |
-amin n | 存取時間 | |
-cmin n | 狀態改變時間 | |
| 大小 | -size n[cwbkMG] | n 區塊 (預設 512B),c=位元組、k=KB、M=MB、G=GB | -size +100M (大於 100MB) |
| +n 大於、-n 小於、n 等於 | |
| 類型 | -type f | 普通檔案 | |
-type d | 目錄 |
-type l | 符號連結 |
-type c | 字元裝置 |
-type b | 區塊裝置 |
-type s | Socket |
-type p | 命名管道 (FIFO) |
-type D | 門 (Solaris) |
| 權限/擁有者 | -perm 模式 | 權限匹配 (如 -perm -644 包含、-perm /644 任一) | -perm -u=rw,g=r,o=r |
| -user 名稱/UID | 擁有者 | -user www |
| -group 名稱/GID | 所屬群組 | -group developers |
| 深度控制 | -maxdepth n | 最大遞歸深度 (0=僅當前目錄) | -maxdepth 2 |
| -mindepth n | 最小深度 (1=至少一層子目錄) | -mindepth 1 |
邏輯組合與分組
# OR 邏輯:匹配 .txt 或 .log
find . \( -name "*.txt" -o -name "*.log" \)
# NOT 邏輯:非 .tmp 結尾
find . ! -name "*.tmp"
# 或
find . -not -name "*.tmp"
# 複雜組合:大於 100M 的 .log 檔,或 7 天前修改的 .tmp 檔
find . \( -name "*.log" -a -size +100M \) -o \( -name "*.tmp" -a -mtime +7 \)
# 實用技巧:排除特定目錄 (如 .git、node_modules)
find . -type d \( -name ".git" -o -name "node_modules" \) -prune -o -type f -print
動作選項
| 動作 | 說明 | 範例 |
-print | 輸出路徑 (預設動作) | find . -name "*.c" -print |
-print0 | 以 NUL 字元分隔輸出 (配合 xargs -0 處理特殊檔名) | find . -print0 | xargs -0 grep "TODO" |
-ls | 類似 ls -lids 詳細資訊 | find . -size +10M -ls |
-exec cmd {} \; | 對每個結果執行 cmd,{} 替換為路徑,\ ; 結束 | find . -name "*.tmp" -exec rm {} \; |
-exec cmd {} + | 批次執行,{} 替換為多個路徑 (如 xargs),效能高得多 | find . -name "*.tmp" -exec rm {} + |
-ok cmd {} \; | 執行前互動確認 | find . -name "*.bak" -ok rm {} \; |
-delete | 直接刪除 (find 內建,比 -exec rm 快且安全) | find . -name "*.tmp" -delete |
-printf 格式 | 自訂輸出格式 | find . -printf "%p %s %TY-%Tm-%Td\n" |
實戰場景範例集
| 場景 | 命令 |
| 清理 30 天前的日誌檔 | find /var/log -name "*.log" -mtime +30 -delete |
| 尋找大於 1GB 的檔案 (磁碟清理) | find / -type f -size +1G -ls 2>/dev/null |
| 尋找擁有者為已刪除使用者的檔案 | find / -nouser -o -nogroup -ls |
| 尋找可執行檔 (含 setuid) | find / -type f -perm /u=x,g=x,o=x -ls |
| 尋找包含特定字串的檔案 (配合 grep) | find . -type f -name "*.conf" -exec grep -l "password" {} + |
| 統計程式碼行數 (排除 .git、build) | find . -type f \( -name "*.c" -o -name "*.h" \) -not -path "*/.git/*" -not -path "*/build/*" -exec wc -l {} + |
| 建立檔案清單備份 | find /data -type f -printf "%p|%s|%TY-%Tm-%Td %TH:%TM\n" > filelist.txt |
| 修正權限:目錄 755,檔案 644 | find /web -type d -exec chmod 755 {} +
find /web -type f -exec chmod 644 {} + |
效能優化關鍵
- 優先縮小搜尋範圍: 指定具體路徑而非
/,使用 -maxdepth 限制深度。
- 條件順序: 廉價條件 (名稱、類型、深度) 前置,昂貴條件 (
-exec、-size 需 stat) 後置。
- 使用
-exec ... + 替代 -exec ... \;: 批次執行減少進程建立開銷,效能提升 10-100 倍。
- 大量檔案刪除: 內建
-delete 最快,避免 xargs rm 參數過長問題。
- 配合
xargs -P 並行: find . -type f -print0 | xargs -0 -P 4 -n 100 cmd。
常見坑點
| 坑點 | 正確做法 |
-mtime +7 以為是 7 天前 | +7 意味著「超過 7 天」即 8 天前;-7 是「7 天內」;7 是「正好 7 天前」 |
| 通配符未加引號被 Shell 展開 | 模式必須加引號:-name "*.log",否則 Shell 先展開導致語法錯誤 |
-exec rm {} \; 極慢 | 用 -exec rm {} + 或 -delete |
刪除目錄用 -delete 失敗 | -delete 僅能刪除空目錄/檔案,非空目錄需 -exec rm -r {} + |
| 檔名含空格/換行符導致 xargs 錯誤 | 用 -print0 + xargs -0 |
熟練掌握 find 的條件組合、深度控制、批次動作與效能優化,能將檔案搜尋與批次處理任務從「寫腳本」簡化為「單行命令」,大幅提升運維開發效率。