最直接匹配固定文件名模式用 find -name,支持 shell 通配符需加引号;-regex 匹配全路径且语法复杂,推荐先 -name 再 grep;ls | grep 适合快速验证但不严谨;中文匹配需确保 utf-8 locale。

用 find -name 匹配固定文件名模式
最直接的方式是用 find 的 -name 选项,它支持 shell 通配符(不是正则),比如 *、?、[]。注意:通配符必须用引号包裹,否则 shell 会提前展开,导致匹配失效。
-
find /path -name "log_*.txt"—— 匹配log_a.txt、log_123.txt,但不匹配log.txt(因为*至少匹配一个字符) -
find /path -name "config.?on"—— 匹配config.json、config.yaml,但不匹配config.toml(?只匹配单个字符) -
find /path -name "file[0-9].log"—— 匹配file1.log、file7.log,不匹配file10.log([0-9]只匹配一位数字)
常见坑:find . -name *.log 会报错或漏匹配——因为未加引号时,*.log 被当前 shell 展开成当前目录下已存在的 .log 文件,find 实际收到的是静态文件名列表,而非模式。
用 find -regex 做更精确的文件名正则匹配
find 自带的 -regex 使用的是 Emacs 正则语法(不是 grep 的 BRE/ERE),且默认匹配**整个路径**,不是仅文件名。这点极易出错。
-
find . -regex ".*/rob\|drs\|sos.*"—— 错误:这会匹配含rob的任意路径段(比如./backup/rob_data/file.txt),且|在 Emacs 正则里需转义为\| - 正确写法:
find . -regex ".*/\(rob\|drs\|sos\)\(.[^/]*\)?$$"太复杂,不推荐;更实用的是先用-name粗筛,再用grep过滤输出 - 真正轻量级做法:
find . -print | grep -E '/(rob|drs|sos)(/|$)'—— 这样能准确定位「文件名本身含 rob/drs/sos」,且避免路径干扰
注意:-regex 在不同 find 版本(GNU vs BSD)行为不一致,跨系统脚本慎用。
用 ls | grep -E 快速列出当前目录匹配名
只查当前目录(不递归)、不关心类型(文件/目录都行)、要快速验证模式是否写对,就用这个组合。但注意它本质是文本过滤,不是文件系统语义匹配。
-
ls -A | grep -E "^(rob|drs|sos)"—— 匹配以 rob/drs/sos 开头的条目(^是行首,ls -A包含隐藏文件) -
ls -p | grep -E "(rob|drs|sos)[^/]*$"——-p给目录加/,这样$前的[^/]*能确保匹配的是文件名末尾部分 - 别写
ls | grep "rob\|drs\|sos"—— 没加-E时|是字面量,得写成grep 'rob\|drs\|sos'或grep -E 'rob|drs|sos'
风险点:如果文件名含换行符或特殊 shell 字符,ls 输出可能被截断或解析错;生产环境批量处理请优先用 find。
匹配中文文件名要额外加 -i 和 locale 支持
Linux 默认 locale(如 C)下,find -name 和 grep 对中文支持不稳定;grep 可能因编码问题漏匹配。
- 先确认当前 locale:
locale | grep LC_CTYPE,如果不是zh_CN.UTF-8或类似 UTF-8 设置,grep可能无法正确切分中文字符 - 临时生效:
LC_ALL=zh_CN.UTF-8 grep -i "报告"——-i在中文场景下有时反而帮助识别全半角、简繁体变体 -
find . -name "*报告*" 2>/dev/null—— 加2>/dev/null屏蔽权限错误,避免中文路径报错中断
真正棘手的是混合编码(如 GBK 文件名 + UTF-8 终端),这时 convmv 工具比硬匹配更可靠——模式匹配只是第一层筛选,编码才是底层前提。











