外观
权限与扩展属性
一个文件能不能被打开、修改、删除,在 macOS 上由四层信息共同决定:Unix 权限位、访问控制列表(ACL)、文件标志,以及扩展属性。
ls -l 只显示了第一层。很多「明明是我的文件却动不了」的情况,答案在另外三层里。
开始之前
本文大部分命令只读。会修改状态的命令都单独标注,并给出撤销方法。建议在一个临时目录里练习:
sh
mkdir -p /tmp/perm-test && cd /tmp/perm-test && touch demo.txt1
第一层:Unix 权限位
sh
ls -l demo.txt1
输出形如 -rw-r--r-- 1 yourname staff 0 ...。前十个字符从左到右是:文件类型(- 普通文件、d 目录、l 符号链接),然后三组各三位,分别是所有者、所属组、其他人的读(r)、写(w)、执行(x)权限。
chmod 改权限,chown 改所有者:
sh
chmod 600 demo.txt1
600 是八进制写法:所有者 6(读 4 + 写 2),组和其他人都是 0。再执行一次 ls -l 能看到变成 -rw-------。
对目录来说,x 的含义不是「执行」而是「可以进入」。一个目录有 r 没有 x,你能列出名字却进不去——这是排查目录访问问题时容易忽略的一点。
第二层:ACL
Unix 权限只能表达三种身份。需要更细的规则时,macOS 用 ACL:
sh
ls -le demo.txt1
-e 显示 ACL。普通文件通常没有,输出和 ls -l 一样。看一个确实有 ACL 的位置:
sh
ls -lde ~/Downloads1
-d 表示看目录本身。这里通常能看到 0: group:everyone deny delete 一类的条目——它明确禁止删除,并且优先于权限位。
这解释了一类怪事:权限位显示你有写权限,删除却被拒绝。原因是一条 deny ACL。查看用 ls -le,修改用 chmod -a,但在系统目录上动 ACL 之前请先确认你真的知道那条规则是干什么的。
第三层:文件标志
sh
ls -lO demo.txt1
-O(大写字母 O)显示文件标志。常见的是 uchg——用户不可更改,对应访达「显示简介」里的「已锁定」。
sh
chflags uchg demo.txt1
执行后再尝试 rm demo.txt 会被拒绝。解除:
sh
chflags nouchg demo.txt1
nouchg 就是在标志名前加 no。这一对命令是「文件删不掉但权限看起来正常」的常见答案。
第四层:扩展属性
扩展属性是挂在文件上的额外数据,ls -l 里表现为权限位后面的一个 @:
sh
ls -l@ demo.txt1
列出具体内容:
sh
xattr -l demo.txt1
xattr 是管理扩展属性的命令,-l 列出全部属性及其值。新建的空文件通常什么都没有。从网上下载的文件则不同,常见这几个:
| 属性名 | 含义 |
|---|---|
com.apple.quarantine | 隔离标记:这个文件来自互联网,尚未通过首次打开的安全检查 |
com.apple.metadata:kMDItemWhereFroms | 下载来源网址 |
com.apple.FinderInfo | 访达使用的旧式元数据 |
查看某个下载文件的来源:
sh
xattr -p com.apple.metadata:kMDItemWhereFroms ~/Downloads/某个文件1
-p 打印指定属性的值。输出是二进制 plist,看起来是一串十六进制,可以接着解码:
sh
xattr -p com.apple.metadata:kMDItemWhereFroms ~/Downloads/某个文件 | xxd -r -p | plutil -p -1
xxd -r -p 把十六进制文本还原成二进制(-r 反向转换,-p 纯十六进制格式),plutil -p - 把 plist 以易读形式打印(- 表示从标准输入读)。
关于删除隔离属性
网上很多教程会让你执行 xattr -d com.apple.quarantine 某个应用 来「修复」打不开的应用。这不是标准安装步骤。
隔离属性正是让系统在首次打开时做签名与公证检查的那个标记。删掉它,检查就不再发生——而检查本来是为了发现文件是否被篡改。软件因为它打不开时,正确的处理顺序见应用无法打开,机制背景见SIP 与公证。
确有必要删除时(例如你自己编译的、明确知道来源的文件),命令是:
sh
xattr -d com.apple.quarantine 文件路径1
-d 删除指定属性。这个操作不可撤销——属性删掉就没了,除非重新下载该文件。
两种失败,两种含义
这是本文最实用的一条:
Permission denied1
POSIX 层面的拒绝。改权限位、换所有者、或者用 sudo 通常能解决。
Operation not permitted1
即使用 sudo 也照样出现的话,这不是权限位问题,而是隐私保护(TCC)或系统完整性保护(SIP)在拦截。典型场景是在终端里访问 ~/Library/Mail:
sh
ls ~/Library/Mail1
终端没有完全磁盘访问权限时,这条命令会返回 Operation not permitted。加 sudo 结果一样——因为拦截它的不是权限系统。处理办法见TCC 隐私授权。
学会区分这两行报错,能省下大量在错误方向上的尝试。
检查结果
在测试目录里走一遍,每步都能预测结果:
sh
cd /tmp/perm-test
chmod 000 demo.txt && cat demo.txt1
2
2
应当报 Permission denied。恢复:chmod 644 demo.txt。
sh
chflags uchg demo.txt && rm demo.txt1
应当报操作被拒。解除:chflags nouchg demo.txt。
sh
ls ~/Library/Mail1
若报 Operation not permitted,说明你已经见到了第二类失败。
动手练习
- 在
/tmp/perm-test里用touch建一个文件,用ls -l@eO一次看全四层信息(这些选项可以合并)。 - 用
chflags uchg锁定它,在访达里打开「显示简介」,确认「已锁定」被勾上——命令行与图形界面看到的是同一件事。 - 在访达里取消勾选,回到终端用
ls -lO确认uchg消失了。 - 找一个从浏览器下载的文件,用
xattr -l看它带哪些属性。 rm -rf /tmp/perm-test清理。
成功标准是第 2、3 步——确认图形界面的开关和命令行的标志是同一份数据的两种呈现。以后遇到「访达里显示正常但命令行报错」,你就知道该去看哪几层。