推荐用 find -exec ls -ld {} ; 查递归权限,因其能准确显示每个项自身权限(含目录的可进入性),避免 ls -lR 的噪声、缺失目录权限及不可脚本化问题;stat -c "%a %n" 更适合提取八进制权限。
直接运行 ls -lR 看递归权限,结果里夹杂着每层目录的“总用量”行、符号链接解析失败提示、甚至乱序的目录头信息。它不是为“查权限”设计的,而是为“列内容”服务的——你真正想看的权限字段(比如 -rw-r--r--)反而被淹没在噪声里。
更麻烦的是,ls -lR 对目录自身权限完全不体现:它只列出子项,不显示该目录自己的 drwxr-xr-x。这意味着你根本没法判断 cd 是否可行、cat subdir/file 是否因父目录缺 x 而失败。
awk 或 cut 很难稳定提取权限列x 是“可进入”,文件的 x 是“可执行”,但 ls -lR 不标注类型上下文这个组合强制每个路径都单独走一次 ls -ld,确保看到的是该项自身的权限,而非其内容。尤其对目录,-d 参数让它不展开内部,只输出自己那一行元数据——这才是你排查 “为什么进不去” 或 “为什么打不开” 的关键。
实操建议:
find . -exec ls -ld {} ;
find . -exec ls -ld {} ; 2>/dev/null
find . -type f -exec ls -ld {} ; 2>/dev/null
find . -type d -exec ls -ld {} ; 2>/dev/null
注意:结尾的 ; 不能写成 +——后者会把多个路径拼成一条 ls -ld a b c 命令,一旦其中某个路径不存在或无权读取,整条命令就失败,其余路径全丢。
当你要把权限转成数字(比如检查是否是 755 或 600),stat 比 ls 直接。它的 -c 格式化输出能稳定拿到八进制值,不用手动换算 rw-r--r-- → 644。
常用写法:
find . -exec stat -c "%a %n" {} ; 2>/dev/null
find . -exec stat -c "%a" {} ; 2>/dev/null | sort -u
stat -c "%a %n %C" . —— %C 输出安全上下文,末尾有 . 表示 SELinux 启用,+ 表示 ACL 存在⚠️ macOS 的 stat 不支持 -c,得用 find . -exec ls -ld {} ; | awk '{print $1,$9}' 配合手工映射,但可靠性下降。
Linux 文件系统本身不记录权限被谁、何时、通过什么命令修改过。所谓“递归覆盖产生的记录”,不是像数据库日志那样可回溯的审计流,而是指你执行了类似 chmod -R 755 dir/ 这类操作后,想确认哪些文件真的被改了、哪些因权限不足跳过了。
这时唯一可靠的方式是提前留痕:
find dir/ -exec stat -c "%a %n" {} ; > before-perm.txt
chmod -R 后再导出:find dir/ -exec stat -c "%a %n" {} ; > after-perm.txt
diff before-perm.txt after-perm.txt
别指望 ls 或 stat 自带“变更历史”——它们只反映当前状态。真正的权限审计需依赖 auditd 或开启 syslog 记录 chmod 系统调用,那已是运维级配置,不在基础查看范畴内。