Linux教程 / 第 40 节
第4章:文件查找与搜索
掌握强大的文件查找和内容搜索工具
本章目标
- 掌握find命令查找文件
- 学会使用grep搜索文件内容
- 了解locate快速定位文件
- 掌握正则表达式基础
- 能够快速定位配置文件和日志错误
4.1 按名称查找文件 (find)
4.1.1 find命令基础
find是Linux中最强大的文件查找工具。
基本语法
find [路径] [选项] [表达式]
基本用法
# 查找当前目录下的所有文件
find .
# 查找指定目录下的所有文件
find /home/jack
# 查找根目录下的所有文件 (慎用,会很慢)
find /
4.1.2 按文件名查找
# 按文件名查找 (-name,区分大小写)
find . -name "file.txt"
# 不区分大小写 (-iname)
find . -iname "file.txt"
# 使用通配符
find . -name "*.txt" # 所有.txt文件
find . -name "test*" # 以test开头的文件
find . -name "*config*" # 包含config的文件
# 查找多种类型的文件
find . -name "*.txt" -o -name "*.md"
# -o 表示 OR (或)
# 排除某些文件
find . -name "*.txt" ! -name "test*"
# ! 表示 NOT (非)
4.1.3 按文件类型查找
# 按类型查找 (-type)
find . -type f # 普通文件 (file)
find . -type d # 目录 (directory)
find . -type l # 符号链接 (symbolic link)
find . -type b # 块设备
find . -type c # 字符设备
find . -type s # socket
find . -type p # 管道
# 组合使用
find . -type f -name "*.txt" # 查找所有.txt文件
find . -type d -name "test*" # 查找以test开头的目录
4.1.4 按文件大小查找
# 按大小查找 (-size)
find . -size 100c # 恰好100字节 (c=bytes)
find . -size 100k # 恰好100KB (k=kilobytes)
find . -size 100M # 恰好100MB (M=megabytes)
find . -size 1G # 恰好1GB (G=gigabytes)
# 大于/小于
find . -size +100M # 大于100MB
find . -size -1M # 小于1MB
# 范围查找
find . -size +10M -size -100M # 10MB到100MB之间
# 实用示例
find . -type f -size +100M # 查找大于100MB的文件
find /var/log -size +1G # 查找大于1GB的日志文件
4.1.5 按时间查找
# 按修改时间查找 (-mtime: modification time)
find . -mtime 0 # 最近24小时内修改
find . -mtime -7 # 最近7天内修改
find . -mtime +30 # 30天前修改
# 按访问时间查找 (-atime: access time)
find . -atime -7 # 最近7天内访问
# 按状态改变时间查找 (-ctime: change time)
find . -ctime -7 # 最近7天内状态改变
# 按分钟查找
find . -mmin -60 # 最近60分钟内修改
find . -mmin +120 # 120分钟前修改
# 实用示例
find . -type f -mtime -1 # 查找昨天修改的文件
find /var/log -mtime +7 # 查找7天前的日志
find . -name "*.log" -mtime +30 # 查找30天前的日志文件
4.1.6 按权限查找
# 按权限查找 (-perm)
find . -perm 644 # 恰好是644权限
find . -perm -644 # 至少包含644权限
find . -perm /644 # 包含任意一个权限位
# 查找可执行文件
find . -type f -perm -111 # 所有人都可执行
find . -type f -perm /111 # 任何人可执行
# 查找有SUID权限的文件
find / -perm -4000 2>/dev/null
# 实用示例
find . -type f -perm 777 # 查找777权限的文件(安全检查)
4.1.7 按所有者查找
# 按用户查找 (-user)
find . -user jack
# 按组查找 (-group)
find . -group developers
# 查找没有所有者的文件
find . -nouser
# 查找没有所属组的文件
find . -nogroup
# 实用示例
find /home -user jack -name "*.txt"
4.1.8 组合条件查找
# AND 条件 (默认)
find . -type f -name "*.txt" -size +1M
# 查找大于1MB的.txt文件
# OR 条件 (-o)
find . -name "*.txt" -o -name "*.md"
# 查找.txt或.md文件
# NOT 条件 (!)
find . -type f ! -name "*.txt"
# 查找非.txt文件
# 复杂组合
find . \( -name "*.txt" -o -name "*.md" \) -size +1M
# 查找大于1MB的.txt或.md文件
4.1.9 对查找结果执行操作
# 删除查找到的文件 (-delete)
find . -name "*.tmp" -delete
# 执行命令 (-exec)
find . -name "*.txt" -exec cat {} \;
# {} 代表找到的文件, \; 表示命令结束
# 批量重命名
find . -name "*.txt" -exec mv {} {}.bak \;
# 批量修改权限
find . -type f -exec chmod 644 {} \;
find . -type d -exec chmod 755 {} \;
# 显示详细信息
find . -name "*.log" -exec ls -lh {} \;
# 使用xargs (更高效)
find . -name "*.txt" | xargs cat
find . -name "*.log" | xargs grep "ERROR"
# 交互式确认 (-ok)
find . -name "*.tmp" -ok rm {} \;
# 每个文件都会询问是否执行
4.1.10 实用示例
# 查找并删除空文件
find . -type f -empty -delete
# 查找并删除空目录
find . -type d -empty -delete
# 查找重复文件 (按大小)
find . -type f -exec ls -l {} \; | sort -k5 -n
# 查找最大的10个文件
find . -type f -exec ls -lh {} \; | sort -k5 -hr | head -10
# 查找并压缩旧日志
find /var/log -name "*.log" -mtime +7 -exec gzip {} \;
# 查找并统计代码行数
find . -name "*.js" -exec wc -l {} \; | awk '{sum+=$1} END {print sum}'
# 查找最近修改的文件
find . -type f -mtime -1 -ls
# 查找包含特定内容的文件
find . -type f -name "*.txt" -exec grep -l "keyword" {} \;
4.2 搜索文件内容 (grep)
4.2.1 grep命令基础
grep = Global Regular Expression Print
基本语法
grep [选项] "搜索模式" [文件]
基本用法
# 在文件中搜索
grep "hello" file.txt
# 在多个文件中搜索
grep "hello" file1.txt file2.txt
# 从标准输入搜索
cat file.txt | grep "hello"
ps aux | grep "nginx"
4.2.2 常用选项
# 忽略大小写 (-i: ignore case)
grep -i "hello" file.txt
# 显示行号 (-n: line number)
grep -n "hello" file.txt
# 显示匹配的行数 (-c: count)
grep -c "hello" file.txt
# 只显示文件名 (-l: files with matches)
grep -l "hello" *.txt
# 显示不匹配的行 (-v: invert match)
grep -v "hello" file.txt
# 显示匹配的内容 (-o: only matching)
grep -o "hello" file.txt
# 递归搜索目录 (-r: recursive)
grep -r "hello" /path/to/dir
# 显示匹配行的前后几行
grep -A 3 "hello" file.txt # 显示后3行 (After)
grep -B 3 "hello" file.txt # 显示前3行 (Before)
grep -C 3 "hello" file.txt # 显示前后3行 (Context)
# 使用扩展正则表达式 (-E)
grep -E "hello|world" file.txt
# 从文件读取搜索模式 (-f)
grep -f patterns.txt file.txt
# 显示不包含模式的文件 (-L)
grep -L "hello" *.txt
4.2.3 正则表达式基础
基本正则表达式
# 匹配任意字符 (.)
grep "h.llo" file.txt # 匹配 hello, hallo, hxllo
# 匹配行首 (^)
grep "^hello" file.txt # 匹配以hello开头的行
# 匹配行尾 ($)
grep "hello$" file.txt # 匹配以hello结尾的行
# 匹配空行
grep "^$" file.txt
# 字符集 ([])
grep "[aeiou]" file.txt # 匹配包含元音字母的行
grep "[0-9]" file.txt # 匹配包含数字的行
grep "[a-z]" file.txt # 匹配包含小写字母的行
# 否定字符集 ([^])
grep "[^0-9]" file.txt # 匹配不包含数字的字符
# 重复 (*)
grep "hel*o" file.txt # 匹配 heo, helo, hello, helllo
# 至少一次 (\+)
grep "hel\+o" file.txt # 匹配 helo, hello, helllo
# 零次或一次 (\?)
grep "hel\?o" file.txt # 匹配 heo, helo
# 精确重复 (\{n\})
grep "hel\{2\}o" file.txt # 匹配 hello
grep "hel\{2,4\}o" file.txt # 匹配 hello, helllo, hellllo
扩展正则表达式 (使用 -E 或 egrep)
# OR 操作 (|)
grep -E "hello|world" file.txt
# 分组 (())
grep -E "(hello|world) (foo|bar)" file.txt
# 重复 (+, ?, {})
grep -E "hel+o" file.txt # 至少一个l
grep -E "hel?o" file.txt # 零个或一个l
grep -E "hel{2,4}o" file.txt # 2到4个l
# 单词边界 (\b)
grep -E "\bhello\b" file.txt # 精确匹配单词hello
4.2.4 实用示例
# 查找IP地址
grep -E "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" file.txt
# 查找邮箱地址
grep -E "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}" file.txt
# 查找URL
grep -E "https?://[a-zA-Z0-9./?=_-]+" file.txt
# 查找日志中的错误
grep -i "error\|fail\|exception" /var/log/syslog
# 查找进程
ps aux | grep nginx
# 查找监听的端口
netstat -tuln | grep LISTEN
# 统计关键字出现次数
grep -o "hello" file.txt | wc -l
# 查找配置文件中的非注释行
grep -v "^#" /etc/nginx/nginx.conf | grep -v "^$"
# 高亮显示匹配内容 (--color)
grep --color "hello" file.txt
# 递归搜索项目中的TODO
grep -rn "TODO" src/
# 搜索多个关键字
grep -E "error|warning|critical" /var/log/app.log
4.3 快速定位文件 (locate)
4.3.1 locate命令
locate通过数据库快速查找文件,比find快得多。
# 安装locate (如果没有)
sudo apt install mlocate # Ubuntu/Debian
sudo yum install mlocate # CentOS/RHEL
# 更新数据库
sudo updatedb
# 查找文件
locate file.txt
# 忽略大小写
locate -i file.txt
# 只显示存在的文件
locate -e file.txt
# 限制结果数量
locate -n 10 file.txt
# 统计匹配数量
locate -c file.txt
# 使用正则表达式
locate -r "\.txt$"
locate vs find
| 特性 | locate | find |
|---|---|---|
| 速度 | 很快 | 较慢 |
| 实时性 | 依赖数据库更新 | 实时 |
| 功能 | 只能按名称查找 | 功能强大 |
| 使用场景 | 快速查找文件名 | 复杂查找条件 |
4.3.2 which / whereis
# which - 查找命令的路径
which ls
# 输出: /usr/bin/ls
which python3
# 输出: /usr/bin/python3
# whereis - 查找命令、源码、手册
whereis ls
# 输出: ls: /usr/bin/ls /usr/share/man/man1/ls.1.gz
whereis nginx
# 输出: nginx: /usr/sbin/nginx /etc/nginx /usr/share/man/man1/nginx.1.gz
4.4 实战场景:查找配置文件和日志错误
场景1: 查找配置文件
# 查找nginx配置文件
find /etc -name "nginx.conf" 2>/dev/null
# 或使用locate
locate nginx.conf
# 查找所有配置文件
find /etc -name "*.conf"
# 查找最近修改的配置文件
find /etc -name "*.conf" -mtime -7
# 查找包含特定配置的文件
grep -r "listen 80" /etc/nginx/
场景2: 查找日志中的错误
# 查找包含ERROR的日志行
grep "ERROR" /var/log/app.log
# 查找最近的错误 (显示后10行)
grep "ERROR" /var/log/app.log | tail -10
# 查找错误并显示上下文
grep -C 5 "ERROR" /var/log/app.log
# 查找多种错误类型
grep -E "ERROR|WARN|FATAL" /var/log/app.log
# 统计错误数量
grep -c "ERROR" /var/log/app.log
# 查找今天的错误
grep "$(date +%Y-%m-%d)" /var/log/app.log | grep "ERROR"
# 查找所有日志文件中的错误
find /var/log -name "*.log" -exec grep -l "ERROR" {} \;
# 实时监控错误日志
tail -f /var/log/app.log | grep --color "ERROR"
场景3: 查找大文件
# 查找大于100MB的文件
find / -type f -size +100M 2>/dev/null
# 查找并显示大小
find / -type f -size +100M -exec ls -lh {} \; 2>/dev/null
# 查找最大的10个文件
find / -type f -exec ls -lh {} \; 2>/dev/null | sort -k5 -hr | head -10
# 查找并删除临时大文件
find /tmp -type f -size +1G -mtime +7 -delete
场景4: 查找重复文件
# 按大小查找可能重复的文件
find . -type f -exec ls -l {} \; | awk '{print $5, $9}' | sort | uniq -d -w 10
# 使用fdupes工具 (需要安装)
sudo apt install fdupes
fdupes -r /path/to/dir
场景5: 清理旧文件
# 查找30天前的日志文件
find /var/log -name "*.log" -mtime +30
# 删除30天前的日志
find /var/log -name "*.log" -mtime +30 -delete
# 压缩7天前的日志
find /var/log -name "*.log" -mtime +7 -exec gzip {} \;
# 删除空文件和空目录
find . -type f -empty -delete
find . -type d -empty -delete
4.5 常用命令速查
| 命令 | 说明 | 示例 |
|---|---|---|
find | 查找文件 | find . -name "*.txt" |
find -type | 按类型查找 | find . -type f |
find -size | 按大小查找 | find . -size +100M |
find -mtime | 按时间查找 | find . -mtime -7 |
find -exec | 执行命令 | find . -name "*.txt" -exec cat {} \; |
grep | 搜索内容 | grep "hello" file.txt |
grep -r | 递归搜索 | grep -r "hello" dir/ |
grep -i | 忽略大小写 | grep -i "hello" file.txt |
grep -n | 显示行号 | grep -n "hello" file.txt |
grep -v | 反向匹配 | grep -v "hello" file.txt |
locate | 快速查找 | locate file.txt |
which | 查找命令路径 | which ls |
4.6 常见问题与解决
Q1: find命令太慢怎么办?
# 限制搜索深度
find . -maxdepth 3 -name "*.txt"
# 使用locate代替
locate file.txt
# 排除某些目录
find . -path ./node_modules -prune -o -name "*.txt" -print
Q2: 如何排除某些目录?
# 排除node_modules
find . -path ./node_modules -prune -o -name "*.js" -print
# 排除多个目录
find . \( -path ./node_modules -o -path ./.git \) -prune -o -name "*.js" -print
Q3: grep如何显示文件名?
# 默认多个文件会显示文件名
grep "hello" *.txt
# 单个文件强制显示文件名 (-H)
grep -H "hello" file.txt
# 不显示文件名 (-h)
grep -h "hello" *.txt
Q4: 如何搜索二进制文件?
# grep默认会跳过二进制文件
# 强制搜索 (-a)
grep -a "hello" binary-file
# 或使用strings
strings binary-file | grep "hello"
Q5: 如何提高grep性能?
# 使用固定字符串搜索 (-F)
grep -F "hello" large-file.txt
# 限制搜索的文件类型
grep "hello" --include="*.txt" -r .
# 排除某些文件
grep "hello" --exclude="*.log" -r .
4.7 本章小结
本章学习了文件查找与搜索:
✅ find命令: 按名称、类型、大小、时间查找文件
✅ grep命令: 搜索文件内容,支持正则表达式
✅ locate命令: 快速定位文件
✅ 正则表达式: 掌握基本的正则表达式语法
✅ 实战应用: 查找配置文件、日志错误、大文件
关键要点
- find功能强大但较慢,locate快速但依赖数据库
- grep支持正则表达式,可以进行复杂的内容搜索
- 善用管道组合命令,提高搜索效率
- 使用-exec或xargs对查找结果批量操作
下一步学习
- 第5章: 文件编辑与处理 - 学习vim、sed、awk
4.8 练习题
- 基础练习: 查找当前目录下所有.txt文件,并统计总数
- 进阶练习: 查找7天前修改的日志文件,并压缩它们
- 实战练习: 在项目中查找所有包含"TODO"的代码文件
- 挑战练习: 编写脚本,查找并删除重复文件
🎉 恭喜!你已经掌握了文件查找与搜索!
继续学习 → 第5章:文件编辑与处理