chown -r 是唯一能递归修改目录及其所有子文件、子目录、隐藏文件所有权和所属组的方式,不加 -r 仅修改目标目录自身,子项完全不变——这是最常踩的坑。

chown -R 递归修改目录时只改了目录本身?
不加 -R 就不会进子目录,这是最常踩的坑。比如执行 chown www-data:www-data /var/www/html,结果只有 html 这个目录的属主变了,里面所有文件、子目录全保持原样——Nginx 很可能因此报 403 Forbidden。
必须显式加 -R:
sudo chown -R www-data:www-data /var/www/html
-
-R会遍历所有层级,包括隐藏文件(如.env)、深层嵌套的node_modules子目录 - 若路径含空格,务必用引号包裹:
sudo chown -R user:group "/path/to/my project" - 误写成
-r(小写)在某些老系统上可能被忽略,坚持用-R(大写)更稳妥
批量改多个不连续路径,怎么避免重复敲 sudo chown?
别一个个手敲。用 shell 的花括号展开或 find 配合 -exec 更可靠:
多个同级目录:
sudo chown -R deploy:deploy /opt/app/{logs,cache,uploads}
按条件筛选(比如只改 .log 文件):
find /var/log -name "*.log" -exec chown syslog:adm {} \;
- 花括号展开不支持嵌套路径,
{a,b}/c不等价于a/c b/c,要写成a/c b/c或用find -
find ... -exec chown ... {} \;中的{}是占位符,\;是exec的终止符,漏掉会报错 - 大量文件时加
-print先预览:find /path -name "*.conf" -print
符号链接的属主到底改的是谁?
默认情况下,chown 对符号链接不做任何操作——它直接跳过去,去改链接指向的目标文件。想改链接文件本身的属主(比如让 current -> releases/20260613 这个 current 文件归你所有),必须加 -h:
sudo chown -h deploy:deploy current
- 加了
-R再加-h,会递归处理每一层符号链接自身,而不是目标内容 - 没加
-h却希望跳过符号链接?不行。chown没提供“跳过链接”的开关,只能先find -type f过滤掉链接再处理 - 用
ls -ld linkname看第一列权限位开头是l,确认是链接;ls -l linkname看箭头指向哪,区分目标和自身
为什么 chown 报 Operation not permitted 却没提示?
常见原因不是权限不够,而是文件被设了不可变属性(immutable)。这种状态下,即使 root 也改不了属主:
先检查:lsattr file → 如果输出含 i(如 ----i--------e---),说明被锁死了
解锁(需 root):chattr -i file
- 容器里执行失败?检查是否挂载时用了
uid=1001,gid=1001强制映射,或者容器没以--user root启动 - 静默失败(无报错但没生效)?大概率漏了
sudo,普通用户对非自有目录执行chown -R会直接跳过,不报错也不改 - NFS 或其他网络文件系统上
chown可能静默失败,先stat file看File:行的Device:是否为本地设备号,再决定是否该去服务端操作
真正麻烦的不是语法,而是改完之后权限链是否断裂——比如 Web 目录属主变了,但 PHP-FPM 还是以旧用户身份运行,或者 SELinux 上下文没同步更新。动手前最好先 ls -lZ 看一眼上下文,留个底。











