執行 find . -name *.php 卻報錯 find: paths must precede expression,這是 Shell 通配符展開導致的經典陷阱。本文從原理到實戰,徹底解決 find 模式匹配問題。

# 當前目錄有 a.php b.php c.php
find . -name *.php
# Shell 先展開 *.php → a.php b.php c.php
# 實際執行變為:
find . -name a.php b.php c.php
# find 將 b.php 視為路徑參數,報錯「paths must precede expression」
| 寫法 | 命令示例 | 原理 | 適用性 |
|---|---|---|---|
| 單引號包裹 | find . -name '*.php' | 單引號阻止 Shell 展開,傳遞字面字串給 find | 最通用、最推薦 |
| 反斜杠轉義 | find . -name \*.php | 轉義 * 避免展開 | 簡短、交互式常用 |
| 雙引號包裹 | find . -name \"*.php\" | 雙引號同樣阻止通配符展開(但允許變數展開) | 需變數插值時使用 |
# 多條件 OR 邏輯
find . \( -name '*.php' -o -name '*.html' -o -name '*.js' \)
# 正則表達式 (需 -regex 或 -iregex)
find . -regex '.*\.\(php\|html\|js\)$'
# 排除目錄
find . -path ./vendor -prune -o -name '*.php' -print
# 組合動作:查找並刪除 30 天前 .log
find /var/log -name '*.log' -mtime +30 -delete
# 查找大文件
find / -type f -size +100M -exec ls -lh {} \;
find: missing argument to '-name' → 模式為空,檢查引號是否成對find: unknown predicate → 拼寫錯誤,如 -mtime 寫成 -mtimPermission denied → 加 2>/dev/null 抑制錯誤輸出,或用 sudo# ~/.bashrc
ff() { find . -type f -name "*$1*" 2>/dev/null; } # 模糊查找文件
fd() { find . -type d -name "*$1*" 2>/dev/null; } # 模糊查找目錄
fe() { find . -type f -name "*.$1" 2>/dev/null; } # 按副名查找
# 使用
fe php
ff config
Shell 先展開,命令後執行 是 Unix 哲學核心。任何涉及通配符、括號、特殊字符的命令參數,**務必用單引號包裹**。養成 find . -name 'pattern' 肌肉記憶,能避開 90% 的 find 參數解析錯誤。