find - 查找文件和目录

find 从指定路径开始遍历目录树,并对每个项目计算表达式。不指定起始路径时,GNU find 使用当前目录。

常用条件

条件作用
-name PATTERN按名称匹配,区分大小写
-iname PATTERN按名称匹配,忽略大小写
-type f普通文件
-type d目录
-type l符号链接
-size +10M大于 10 MiB
-mtime +N按完整的 24 小时时段筛选修改时间
-mmin +N按分钟筛选修改时间
-user NAME文件所有者
-maxdepth N最大遍历深度,GNU 扩展
-mindepth N最小匹配深度,GNU 扩展

Shell 会先处理通配符,因此名称模式通常需要加引号:

find . -type f -name '*.log'

使用示例

# 当前目录下的普通文件
find . -maxdepth 1 -type f
 
# 忽略大小写查找 Markdown 文件
find notes -type f -iname '*.md'
 
# 大于 100 MiB 的文件
find . -type f -size +100M
 
# 修改时间不足一天的文件
find . -type f -mtime -1
 
# 同时匹配两种扩展名
find . -type f \( -name '*.txt' -o -name '*.md' \)

-mtime 会先把经过时间除以 24 小时并向下取整。因此 -mtime 0 表示不足一个完整 24 小时,-mtime +1 表示至少经过两个完整的 24 小时时段。

对结果执行命令

# 每个文件执行一次 file
find . -type f -exec file -- {} \;
 
# 尽量把多个路径合并到一次命令中
find . -type f -name '*.txt' -exec wc -l -- {} +
 
# 每次执行前询问
find . -type f -name '*.bak' -ok printf '%s\n' {} \;

;+ 用来结束 -exec-ok 的命令部分;分号需要转义或引用,避免被 Shell 当作命令分隔符。

需要把路径传给其他工具时,应使用不会被空格、换行或引号破坏的 NUL 分隔:

find . -type f -print0 | xargs -0 -r file --

详见 xargs

安全提示

  • 删除或批量修改前,先用同一组筛选条件只输出路径并人工核对。
  • 不要使用未经引用的 Shell 通配符作为起始路径,否则 Shell 可能在 find 启动前展开为意外范围。
  • 从受其他用户写入的目录处理文件时,优先使用 -exec ... {} +,减少“先输出路径、后处理”之间的竞态。
  • 对根目录或大型挂载点执行前应限制路径、深度或文件系统范围,避免不必要的负载。

参考资料