按名称、类型、时间和扩展属性遍历目录树,macOS 版是 BSD find。
find 从给定路径开始递归遍历,对每个条目依次求值表达式,只有整个表达式为真的条目才执行 -print、-delete 或 -exec。常用原语包括 -name/-iname、-type、-size、-mtime、-newer、-maxdepth、-print0 和 -exec ... {} +。macOS 还提供 -flags、-xattr、-xattrname、-acl 等 BSD 扩展,适合查文件标志和扩展属性。
与 GNU 的关键差异:macOS 没有 -printf,格式化输出要用 -exec stat -f ... 或 -ls;正则用 -E 加 -regex,没有 GNU 的 -regextype。-delete 在 macOS 上可用,但会立即删除求值到的条目,表达式顺序写错就可能删错。
macOS 的根卷是只读系统卷,/Users、/Applications 等通过 firmlink 接到数据卷,遍历 / 时同一批文件可能出现两次。搜索用户目录通常直接从 ~ 开始,并加 -x 避免跨挂载点。受 TCC 保护的目录需要给终端完全磁盘访问权限,否则会报 Operation not permitted。
# 只在项目下两层内找 Swift 文件,避免扫描依赖目录
% find ~/Projects -maxdepth 2 -type f -name '*.swift'
# 找大于 1 GB 的文件
% find ~/ -type f -size +1G -print 2>/dev/null
# 先预览再删除 .DS_Store,确认路径范围后再执行第二条
% find ~/Downloads -name '.DS_Store' -print
% find ~/Downloads -name '.DS_Store' -delete
# 查用户锁定标志(uchg)的文件,解释“为什么删不掉”
% find ~/Documents -flags uchg -print
# 找仍带 quarantine 扩展属性的下载文件
% find ~/Downloads -xattrname com.apple.quarantine -print
# 对结果执行 stat,替代 GNU find 的 -printf
% find . -type f -name '*.log' -exec stat -f '%N %z %Sm' {} +
# 用 NUL 分隔结果,安全处理带空格和换行的文件名
% find . -type f -print0 | xargs -0 du -h
find -printf '%p %s\n' 会报 unknown primary。macOS 改用 -exec stat -f '%N %z' {} +,或先用 -ls 看默认格式。-delete 求值即删除,且隐含深度优先;如果它写在 -name 前面,可能删掉整棵树。永远先跑 -print 版本,确认后再替换。-E 用于启用 -regex/-iregex 的现代正则;GNU 用 -regextype 指定正则方言。移植脚本时去掉 -regextype,改用 -E 并确认正则语法。~/Library、~/Desktop 等位置可能因 TCC 返回空结果或 Operation not permitted;给终端授权后再试,不要误判为文件不存在。/ 开始搜索会同时经过系统卷和数据卷,速度慢且可能重复。限制到用户目录,或用 -x 不跨挂载点。-exec 直接传参是安全的,但 find ... | xargs 不安全;管道必须用 -print0 配合 xargs -0。mdfind — 用 Spotlight 索引快速搜索,适合全盘找内容。xattr — 查看 -xattrname 命中的属性值。touch — 生成 -newer 所需的参考时间文件。find — GNU 版对照,重点看 -printf 和 -regextype。where — Windows 下按名称查找可执行文件。find 速查 — 常见组合与表达式优先级。合上页面,先回答,再展开对照。
find 没有 -printf,用什么替代输出文件名和大小?-delete 必须放在表达式末尾?执行前应做什么?-E 和 GNU 的 -regextype 各起什么作用?-exec stat -f '%N %z' {} + 或 -ls。-print 版本预览。-E 启用 BSD 的现代正则,-regextype 是 GNU 用来选择正则方言的选项。
小程序版
微信扫码,随时查命令