「Linux文件及目录管理」通配符与文件名
知识点解析
通配符是Linux中用于匹配文件名的特殊字符,能高效处理批量文件操作。 常见通配符包括:
*:匹配任意字符序列(包括空字符)touch a b ab a123 # 创建测试文件 ls a* # 匹配a, ab, a123?:精确匹配单个字符touch file1.txt file2.txt file10.txt ls file?.txt # 仅匹配file1.txt, file2.txt[]:匹配指定范围内的单个字符(如[a-z])ls [a-c]*.txt # 匹配以a/b/c开头的.txt文件 ls [0-9][0-9].txt # 匹配两位数字开头的.txt文件[^]:匹配不在指定范围内的字符ls [^a]*.txt # 匹配不以a开头的.txt文件
特殊场景处理
- 隐藏文件匹配:
.*(需谨慎使用) - 递归匹配:需结合
find命令 - 大小写敏感:
[A-Z]和[a-z]需分开处理
适用场景:
- 批量删除日志文件
- 快速定位特定格式文件
- 组合命令实现复杂筛选
案例解析
案例:批量删除旧日志文件
# 删除当前目录下所有.log文件(保留最近3天)
find . -name "*.log" -mtime +3 -exec rm {} \;
# 使用通配符简化(仅适用于当前目录)
rm *.log
解析:
find命令结合-name和-mtime实现精准筛选- 通配符
*.log直接匹配所有.log文件,但无法处理子目录
案例:重命名特定格式文件
# 创建测试文件
touch file{1..5}.txt
ll *.txt
# -rw-r--r-- 1 root root 0 6月 21 09:10 file1.txt
# -rw-r--r-- 1 root root 0 6月 21 09:10 file2.txt
# -rw-r--r-- 1 root root 0 6月 21 09:10 file3.txt
# -rw-r--r-- 1 root root 0 6月 21 09:10 file4.txt
# -rw-r--r-- 1 root root 0 6月 21 09:10 file5.txt
# 将所有.txt文件重命名为.bak
find . -name "*.txt" -exec bash -c 'mv "$0" "${0%.txt}.bak"' {} \;
ll *.bak # 将所有.txt文件重命名为.bak
-rw-r--r-- 1 root root 0 6月 21 09:10 file1.bak
-rw-r--r-- 1 root root 0 6月 21 09:10 file2.bak
-rw-r--r-- 1 root root 0 6月 21 09:10 file3.bak
-rw-r--r-- 1 root root 0 6月 21 09:10 file4.bak
-rw-r--r-- 1 root root 0 6月 21 09:10 file5.bak
解析:
find .:从当前目录开始递归查找-name "*.txt":仅匹配扩展名为 .txt 的文件-exec ... \;:对查找到的每个文件执行自定义命令bash -c 'mv "$0" "${0%.txt}.bak"':启动子 Shell 执行重命名操作{}:占位符,表示当前查找到的文件路径\;:标记 -exec 操作结束${0%.txt}:删除文件名末尾的.txt
案例:筛选特定字符文件
# 创建测试文件
touch a11 b11 c b.jpg c.png
ll
# -rw-r--r-- 1 root root 0 6月 21 09:17 a11
# -rw-r--r-- 1 root root 0 6月 21 09:17 b11
# -rw-r--r-- 1 root root 0 6月 21 09:17 b.jpg
# -rw-r--r-- 1 root root 0 6月 21 09:17 c
# -rw-r--r-- 1 root root 0 6月 21 09:17 c.png
# 列出所有以a-c开头且长度为3的文件
ls [a-c]??
# a11 b11
# 列出所有非.jpg文件
ls *[^.jpg]
# a11 b11 c
解析:
[a-c]??组合范围匹配和长度匹配[^.jpg]实际会匹配非"j"、"p"、"g"的任意字符,需注意此用法不严谨
案例:批量压缩特定格式文件
# 创建测试文件
mkdir backup && cd backup
touch report1.pdf report2.docx report3.pdf data.csv
# 压缩所有PDF文件
find . -name "*.pdf" -exec sh -c 'cp "$0" "$0.bak" && gzip --best "$0"' {} \;
# 验证结果
ls *.gz
# report1.pdf.gz report3.pdf.gz
解析:
find .:从当前目录(.)开始递归搜索-name "*.pdf":匹配所有扩展名为 .pdf 的文件-exec:对每个找到的文件执行后续命令sh -c '...':启动子Shell执行复杂命令链(需引号包裹){}:占位符,表示当前处理的PDF文件名(如 file1.pdf)\;:标识命令结束(必须转义)'cp "$0" "$0.bak" && gzip --best "$0"':创建备份。$0:引用传入的PDF文件名(如 file1.pdf)- 创建备份文件:原文件名 + .bak → file1.pdf.bak
gzip --best "$0":压缩原文件--best:使用最高压缩率(速度最慢但体积最小)- 压缩后生成:file1.pdf.gz
&&:逻辑与操作,确保备份成功后才进行压缩(防止数据丢失)
案例:按日期筛选文件
# 创建带时间戳的文件
touch -d "2024-01-01" old_file.txt
touch -d "2024-12-31" new_file.txt
# 结合find和通配符(仅当前目录)
find . -maxdepth 1 -name "*.txt" -newermt "2024-06-01" ! -newermt "2024-12-31"
# ./new_file.txt
解析:
find . -maxdepth 1:目录范围控制.:从当前目录开始搜索-maxdepth 1:搜索当前目录,不进入子目录。如果删除此参数,则会递归搜索所有子目录
-name "*.txt":文件名匹配。精确匹配扩展名为.txt 的文件。-newermt "2024-06-01" ! -newermt "2024-12-31":时间范围过滤。2024-06-01 ≤ 修改时间 ≤ 2024-12-31。-newermt "2024-06-01":修改时间 ≥ 2024-06-01。!:逻辑非运算符-newermt "2024-12-31":修改时间 ≥ 2024-12-31! -newermt "2024-12-31":修改时间 ≤ 2024-12-31
常见错误及解决方案
错误:rm *误删所有文件
解决方案:使用ls *预览匹配结果。
错误:[a-z]不匹配大写字母
解决方案:使用[a-zA-Z]
错误:文件名含空格导致命令失败 解决方案:始终用双引号包裹变量
错误:范围匹配边界问题
# 错误示例
ls [0-9].txt # 实际匹配1字符(0-9)加.txt
# 正确做法
ls [0-9]*.txt # 匹配1位数字开头的.txt文件
ls [0-9][0-9]*.txt # 匹配2位数字开头的.txt文件
错误:递归删除风险
# 危险操作(勿在生产环境执行)
rm -rf * # 递归删除当前目录所有内容
# 安全替代方案
# 1. 先预览
find . -maxdepth 1 -type f
# 2. 使用交互式删除
find . -maxdepth 1 -type f -exec rm -i {} \;
理论练习
多选题:以下哪个通配符能匹配file1.txt和file2.txt?
A) file?.txt B) file*.txt C) file[12].txt
答案:ABC(均能匹配)
单选题:ls [!abc]*会显示什么?
A) 以a/b/c开头的文件 B) 不以a/b/c开头的文件 C) 包含a/b/c的文件
答案:B
单选题:以下哪个命令会匹配data_2023.csv但不匹配data_2023_backup.csv?
A) data_*.csv B) data_[0-9]*.csv C) data_[^_]*.csv
答案:C
解析:
- A会匹配所有以
data_开头的.csv文件 - B会匹配
data_2023.csv和data_2023_backup.csv - C使用
[^_]排除含下划线的文件名
单选题:ls [!x-z]*会显示什么?
A) 以x/y/z开头的文件 B) 不以x/y/z开头的文件 C) 包含x/y/z的文件
答案:B
解析:!或^表示否定范围
实操练习
练习:
- 创建测试目录结构:
touch file1.txt file2.log fileA.txt fileB.log test.sh
- 完成以下操作:
- 删除所有.log文件
- 将所有.txt文件重命名为.bak
- 列出所有以f开头且长度为5的文件
参考答案:
# 1. 删除.log文件
rm *.log
# rm:是否删除普通空文件 "file2.log"?y
# rm:是否删除普通空文件 "fileB.log"?y
# 2. 重命名.txt文件
find . -name "*.txt" -exec bash -c 'mv "$0" "${0%.txt}.bak"' {} \;
# 3. 列出f开头长度5的文件
ls f????.*
# file1.bak fileA.bak
练习:删除所有超过100KB的.bak文件 参考答案:
find . -name "*.bak" -size +100k -exec rm {} \;
练习:
- 创建测试目录结构:
mkdir -p project/{src,docs,test} touch project/src/{main.c,utils.c} touch project/docs/{readme.txt,design.doc} touch project/test/{test1.sh,test2.sh} - 完成以下操作:
- 删除所有
.doc文件 - 将所有
.sh文件重命名为.backup - 列出
project/src下所有.c文件
- 删除所有
参考答案:
# 1. 删除.doc文件
find project -name "*.doc" -delete
# 2. 重命名.sh文件
find project -name "*.sh" -exec bash -c 'mv "$0" "${0%.sh}.backup"' {} \;
# 3. 列出src目录的.c文件
ls project/src/*.c
知识总结
- 通配符在Shell中展开,而非命令内部处理
- 复杂匹配建议结合
find命令 - 操作前务必先预览匹配结果
常用通配符
| 通配符 | 匹配规则 | 示例 | 注意事项 |
|---|---|---|---|
* | 任意字符 | *.log | 慎用rm * |
? | 单个字符 | file?.txt | 区分大小写 |
[abc] | 指定字符 | [a-z]*.txt | 范围需连续 |
[^abc] | 非指定字符 | [^0-9]*.txt | 排除匹配 |