访问符号链接遇拒绝,如何批量修改其目标文件的chmod权限?
批量修改符号链接目标权限的最优实现
先把你疑惑的chown和chmod行为差异说透:这俩工具的默认表现差异根本不是chmod缺了跟随软链接的能力,是POSIX从设计上就给两个命令定了不一样的默认规则:
chown/chgrp默认就会跟着软链接走,直接改目标文件的属主/属组,只有加-h参数的时候才会跳过目标,只碰软链接本身的元数据chmod默认遇到软链接直接绕着走,核心原因是Linux下软链接自身的权限位是完全无效的:所有软链接的权限都是内核硬编码的0777,哪怕你手动chmod修改,内核访问的时候根本不读取这个值,最终访问权限完全由指向的目标文件决定。所以chmod默认根本懒得处理软链接,只有你显式要求时,它才会跟进目标执行操作。
你现有管道方案的常见问题
你这套管道在文件名都是简单无空格的场景下能跑,但稳定性很差,换个环境大概率就会出错:
ls的输出是给人看的,不是给脚本解析的:不同系统的ls、不同终端宽度下,输出的列数、格式都可能变化,你写死提取11到14列的逻辑,遇到长文件名自动换行、带多空格的文件、特殊字符路径时,马上就会提取错误- 从ls输出里抠出来的软链接目标是相对路径:比如软链接在
/var/www/app目录里,标注的目标是../public/index.php,这个路径是相对于软链接所在目录的,不是你执行命令的当前目录,直接拿去chmod,十有八九会报找不到文件的错误 - 手动给路径加引号的处理,遇到文件名本身带双引号的场景直接破防,xargs解析的时候会把路径截断,执行错误的chmod操作
更稳定的可替代实现
所有需要批量处理文件路径的场景,优先使用能提供结构化路径输出的工具,不要依赖文本解析ls的结果,下面几个都是生产环境常用的可靠方案:
最简方案:直接用chmod的原生能力
你以为chmod没有的功能,它本身就原生支持,只是默认不启用:
sudo chmod -R -L 775 /var/www/
加个-L参数就能实现:递归遍历目录时,遇到软链接就自动跟进到目标文件,和普通文件一样执行权限修改,完全匹配你想要的操作逻辑,根本不需要额外拼接管道。
精准方案:仅修改软链接对应的目标文件,不改动普通文件
如果你不想调整目录下普通文件的权限,只需要把所有软链接指向的目标统一调整为775权限,搭配find和readlink实现最稳定:
sudo find /var/www -type l -exec sh -c 'chmod 775 -- "$(readlink -f "$1")"' _ {} \;
这套写法完全不需要纠结空格、特殊字符、路径相对偏移的问题:
-type l直接从文件系统元数据层面筛选软链接,不靠文本输出猜文件类型readlink -f自动把软链接的相对路径转换成目标文件的绝对路径,永远能定位到真实文件- 外层套
sh -c做一层包装,所有带空格、引号甚至换行的文件名都能正常解析,不需要手动处理转义
高效率方案:批量跟进所有软链接统一调整权限
如果你需要递归遍历目录,遇到软链接就自动跟进,对所有遍历到的文件统一调整权限,用find的-L模式执行效率更高:
sudo find -L /var/www -type f -exec chmod 775 {} +
和逐个调用chmod的写法比,这种模式会把收集到的所有目标文件凑成一批一次性传给chmod执行,速度快很多。
额外提醒:别白费功夫修改软链接本身的权限,Linux内核会硬编码忽略软链接的权限位,任何对软链接本身的权限修改都是无效的,所有和软链接相关的权限操作,本质上都是在调整它指向的目标文件权限。
内容的提问来源于stack exchange,提问作者beepbeep
相关产品推荐
相关产品推荐

