「Linux文件及目录管理」通配符与文件名

142 阅读3分钟

「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.txtfile2.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.csvdata_2023_backup.csv
  • C使用[^_]排除含下划线的文件名

单选题ls [!x-z]*会显示什么?
A) 以x/y/z开头的文件 B) 不以x/y/z开头的文件 C) 包含x/y/z的文件
答案:B
解析!^表示否定范围

实操练习

练习

  1. 创建测试目录结构:
touch file1.txt file2.log fileA.txt fileB.log test.sh
  1. 完成以下操作:
    • 删除所有.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 {} \;

练习

  1. 创建测试目录结构:
    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}
    
  2. 完成以下操作:
    • 删除所有.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
知识总结
  1. 通配符在Shell中展开,而非命令内部处理
  2. 复杂匹配建议结合find命令
  3. 操作前务必先预览匹配结果

常用通配符

通配符匹配规则示例注意事项
*任意字符*.log慎用rm *
?单个字符file?.txt区分大小写
[abc]指定字符[a-z]*.txt范围需连续
[^abc]非指定字符[^0-9]*.txt排除匹配