推荐使用 find -exec ls -ld {} ; 递归查看 Linux 文件权限,因为它能准确展示每个文件或目录自身的权限信息(包括目录是否可进入),可以避免 ls -lR 带来的大量噪声、目录权限缺失以及不利于脚本处理的问题;如果需要提取八进制权限,stat -c "%a %n" 会更合适。

ls -lR 会混入大量无关输出,不建议直接用
直接执行 ls -lR 来递归查看权限时,输出中通常会夹杂每层目录的“总用量”行、符号链接解析失败提示,甚至还有不够直观的目录标题信息。它本质上并不是为“查看权限”设计,而是为“列出目录内容”服务的——你真正关心的权限字段(例如 -rw-r--r--)反而容易被这些无关信息淹没。
更麻烦的是,ls -lR 并不会显示目录自身的权限:它只列出目录里的子项,而不会展示该目录本身的 drwxr-xr-x。这意味着你无法准确判断 cd 能否进入目录,或者 cat subdir/file 是否会因为父目录缺少 x 权限而失败。
- 输出不适合脚本处理:字段分隔不固定,使用
awk或cut很难稳定提取权限列 - 无法明确区分文件和目录的权限含义:目录的
x表示“可进入”,文件的x表示“可执行”,但ls -lR缺少清晰的类型上下文提示 - 遇到权限拒绝时会直接报错,递归遍历过程也不够稳定
find -exec ls -ld {} ; 是最稳的递归权限查看方式
这个组合会强制每个路径单独执行一次 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 命令,一旦其中某个路径不存在或没有读取权限,整条命令都可能失败,其余路径的结果也会丢失。
stat -c "%a %n" 更适合自动化提取八进制权限
当你需要把权限转换成数字形式(例如检查是否为 755 或 600)时,stat 比 ls 更直接、更适合自动化处理。它的 -c 格式化输出可以稳定获取八进制权限值,无需手动将 rw-r--r-- 换算成 644。
常用写法:
- 输出当前目录下所有项的八进制权限和路径:
find . -exec stat -c "%a %n" {} ; 2>/dev/null - 只输出权限数字(便于后续用 grep 或 awk 处理):
find . -exec stat -c "%a" {} ; 2>/dev/null | sort -u - 识别 SELinux 或 ACL 标记:
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 自带“权限变更历史”功能——它们只能反映当前状态。真正要做 Linux 权限审计,通常需要依赖 auditd,或者开启 syslog 来记录 chmod 系统调用,这已经属于运维审计级配置,不属于基础权限查看命令的范畴。
