理解 Linux 文件权限,不能只看 chmod。很多日常操作,比如 touch、mkdir、cp、mv、rm、解压、同步、编辑文件,都会直接或间接影响文件的权限、属主、属组、ACL 或特殊权限位。
这篇文章从常见操作出发,具体说明 Linux 文件和文件夹在被创建、复制、移动、删除、编辑、压缩解压、同步之后,权限通常会发生什么变化。
一、先理解 Linux 权限到底记录在哪里
Linux 中每个文件或目录都有一组元数据,主要包括:
ls -l
示例:
-rw-r--r-- 1 user user 1234 Jun 6 test.txt
drwxr-xr-x 2 user user 4096 Jun 6 docs
第一列就是权限信息。以 -rw-r--r-- 为例:
- rw- r-- r--
类型 所有者 所属组 其他人
其中:
| 位置 | 含义 |
|---|---|
- |
普通文件 |
d |
目录 |
l |
符号链接 |
r |
read,读权限 |
w |
write,写权限 |
x |
execute,执行权限 |
对文件来说:
| 权限 | 含义 |
|---|---|
r |
可以读取文件内容 |
w |
可以修改文件内容 |
x |
可以执行文件 |
对目录来说,含义稍微不同:
| 权限 | 含义 |
|---|---|
r |
可以列出目录下的文件名 |
w |
可以在目录内创建、删除、重命名文件 |
x |
可以进入目录,访问目录内文件的元数据或内容 |
目录的 x 权限非常重要。没有 x,即使有 r,也很难正常进入和访问目录。
二、权限变化的核心规则:新建看 umask,已有文件通常不变
Linux 中一个非常核心的规则是:
新建文件或目录时,权限通常由”默认权限 – umask”决定;修改已有文件内容时,权限通常不会变化。
可以查看当前 umask:
umask
常见结果是 0022,这意味着系统会从默认权限中减去对应权限。
Linux 创建新对象时,默认权限一般是:
| 类型 | 原始默认权限 |
|---|---|
| 普通文件 | 666,即 rw-rw-rw- |
| 目录 | 777,即 rwxrwxrwx |
为什么普通文件默认不是 777?因为 Linux 不希望新建的普通文件天然可执行。一个脚本文件即使内容是 shell 脚本,也通常需要手动 chmod +x script.sh 才会变成可执行文件。
如果 umask 是 022,那么新建结果通常是:
- 文件:666 – 022 = 644 →
rw-r--r-- - 目录:777 – 022 = 755 →
rwxr-xr-x
所以,理解权限变化,首先要理解 umask。
三、touch:创建新文件会受 umask 影响,已有文件权限不变
touch 有两种常见情况。
1. 文件不存在时
touch a.txt
这会创建一个新文件。如果当前 umask 是 022,新文件通常是 -rw-r--r-- a.txt,也就是 644。原因是:普通文件默认权限 666,减去 umask 022,得到 644。
2. 文件已经存在时
touch a.txt
如果 a.txt 已经存在,touch 默认只是更新时间戳,不会改变文件权限。例如原来是 -rw------- a.txt,再次执行 touch a.txt 后,权限仍然是 -rw------- a.txt。
touch 创建新文件时会产生权限;touch 更新已有文件时通常不改变权限。
四、mkdir:新建目录会受 umask 影响
mkdir docs
如果 umask 是 022,目录通常是 drwxr-xr-x docs,也就是 755。原因是:目录默认权限 777,减去 umask 022,得到 755。
如果希望指定目录权限,可以使用:
mkdir -m 700 private
结果一般是 drwx------ private,表示只有目录所有者可以进入、查看和修改该目录。
注意:目录权限比文件权限更容易影响实际访问。如果 docs 是目录,
chmod 600 docs通常会导致你无法正常进入目录,因为目录没有 x 权限。
对于目录,常见权限是:
| 权限 | 含义 |
|---|---|
| 700 | 只有自己可访问 |
| 755 | 自己可写,别人可进入和读取 |
| 775 | 自己和同组用户可写,别人可读可进入 |
| 777 | 所有人可写,不安全,除非配合 sticky bit |
五、重定向:> 创建新文件受 umask 影响,覆盖已有文件不改变权限
Shell 重定向也会影响文件权限。
1. 文件不存在时
echo "hello" > a.txt
如果 a.txt 不存在,Shell 会创建它。新文件权限通常与 touch 类似,也受 umask 影响。在 umask 022 下,通常是 -rw-r--r-- a.txt。
2. 文件已经存在时
echo "new content" > a.txt
这会清空原内容并写入新内容,但通常不会改变文件权限。例如原来是 -rw------- a.txt,执行覆盖写入后,仍然是 -rw------- a.txt。
> 创建新文件时,权限由 umask 决定;> 覆盖已有文件时,一般只改内容,不改权限。
3. >> 追加内容也不改变已有文件权限
echo "more" >> a.txt
如果文件已经存在,追加内容通常不改变权限。如果文件不存在,则会新建文件,权限仍然受 umask 影响。
六、cp:复制文件时,目标文件权限不一定完全等于源文件
cp 是最容易让人误解的操作之一。
1. 复制到一个不存在的新文件
cp source.txt target.txt
如果 target.txt 不存在,系统会创建一个新文件。一般来说,目标文件会参考源文件权限,但也可能受到当前用户的 umask 影响。普通复制通常不保证完整保留所有元数据。
2. 复制到已经存在的文件
cp source.txt target.txt
如果 target.txt 已经存在,cp 通常会覆盖其内容,但保留 target.txt 原来的权限。这是因为目标文件已经存在,cp 只是打开它、截断它、写入新内容,而不是重新创建一个权限全新的文件。
3. 使用 cp -p 保留权限和时间戳
cp -p source.txt target.txt
-p 表示 preserve,会尽量保留:权限 mode、时间戳、属主属组(前提是当前用户有权限保留)。普通用户通常不能随便把文件属主设置成其他人,所以属主未必能完整保留。
4. 使用 cp -a 归档复制
cp -a source_dir target_dir
-a 类似”尽可能原样复制”,常用于复制目录。它会尽量保留:文件权限、目录权限、符号链接、属主属组、时间戳、硬链接关系、扩展属性和安全上下文(视系统支持情况而定)。
如果你想复制一个目录,并希望权限尽量不变,通常用
cp -a old_dir new_dir,而不是简单地cp -r old_dir new_dir。
七、mv:同一文件系统内移动,权限通常完全不变
mv 有两种情况。
1. 同一文件系统内移动或重命名
mv a.txt b.txt
mv a.txt /home/user/docs/
如果源和目标在同一个文件系统内,mv 本质上只是改目录项,也就是改变文件”放在哪里”或”叫什么名字”。文件本身的 inode 没变,所以权限、属主、属组、ACL、时间戳等通常都不变。
2. 跨文件系统移动
mv a.txt /mnt/usb/
如果源和目标不在同一个文件系统,mv 实际上更接近复制 + 删除原文件。这时权限一般会尽量保留,但可能受以下因素影响:当前用户权限、目标文件系统是否支持 Linux 权限、是否能保留属主属组、是否支持 ACL 和扩展属性、是否是 FAT32/exFAT/NTFS 等非原生 Linux 文件系统。
同一文件系统内 mv,权限几乎肯定不变;跨文件系统 mv,权限可能发生变化。
八、rm:删除文件不看文件自己的写权限,而看目录权限
很多人以为删除文件需要文件本身有写权限,其实不完全对。
删除一个文件,本质上是修改它所在目录的目录项。所以你是否能删除文件,主要看你对其父目录有没有 w + x(写权限和进入权限)。
例如,-r-------- a.txt(文件本身没有写权限),但如果你对它所在目录有写权限和执行权限,你仍然可能删除它。反过来,如果文件本身是 -rw-rw-rw- a.txt,但你对它所在目录没有写权限,你也不能删除它。
sticky bit 的特殊情况
比如 /tmp 目录通常是 drwxrwxrwt /tmp,最后的 t 就是 sticky bit。在这种目录下,即使大家都有写权限,也不是谁都可以删除别人的文件。通常只有以下用户可以删除:文件所有者、目录所有者、root。所以 /tmp 可以让大家创建临时文件,但不能随便删别人的文件。
九、chmod:直接改变权限
chmod 是最直接修改权限的命令。
1. 数字方式
chmod 644 a.txt
chmod 755 script.sh
chmod 700 private_dir
常见数字含义:
| 数字 | 权限 |
|---|---|
| 7 | rwx |
| 6 | rw- |
| 5 | r-x |
| 4 | r– |
| 0 | — |
2. 符号方式
chmod u+x script.sh
chmod g-w a.txt
chmod o-r secret.txt
chmod a+r readme.md
含义:
| 符号 | 含义 |
|---|---|
u |
user,所有者 |
g |
group,所属组 |
o |
others,其他人 |
a |
all,所有人 |
3. 递归修改目录要小心
chmod -R 755 mydir
这会把目录下所有文件和子目录都改成 755。问题是:普通文本文件也会被加上执行权限。更合理的写法通常是:
find mydir -type d -exec chmod 755 {} \;
find mydir -type f -exec chmod 644 {} \;
这样目录是 755,普通文件是 644。如果只想给目录加执行权限,可以使用大写 X:
chmod -R a+X mydir
X 的意思是:只给目录加执行权限,或者给原本已经有执行权限的文件加执行权限。这比小写 x 更安全。
十、chown 和 chgrp:改变属主属组,也可能影响特殊权限
文件除了权限位,还有属主和属组。
ls -l
# 输出示例:-rw-r--r-- 1 alice staff 1234 Jun 6 a.txt
其中 alice 是属主,staff 是属组。
修改属主:sudo chown bob a.txt
修改属组:chgrp developers a.txt
同时修改:sudo chown bob:developers a.txt
递归修改目录:sudo chown -R bob:developers project/
注意:修改属主或属组时,系统可能会清除 setuid、setgid 等特殊权限位。这是出于安全考虑,防止通过改变属主制造提权风险。
十一、编辑文件:通常权限不变,但要看编辑器如何保存
用编辑器修改文件,例如 vim a.txt 或 nano a.txt,通常情况下,保存后文件权限不会变化。
但是有些工具并不是”原地修改”,而是:创建临时文件 → 写入新内容 → 用新文件替换旧文件。这种情况下,可能出现 inode 变化、硬链接关系断开、ACL 丢失、扩展属性丢失、权限被重新计算、属主属组发生变化等问题。
尤其是在使用
sudo vim a.txt编辑普通用户文件时,更要小心。如果编辑器或保存方式不当,可能导致文件属主变成 root。更安全的做法通常是使用sudoedit a.txt或sudo -e a.txt。
十二、硬链接和符号链接:权限变化逻辑不同
1. 硬链接
ln a.txt b.txt
a.txt 和 b.txt 指向同一个 inode。所以它们不是两个独立文件,而是同一个文件的两个名字。对其中一个执行 chmod 600 a.txt,另一个也会显示为 -rw------- b.txt。因为权限属于 inode,而不是属于文件名。硬链接之间共享同一套权限。
2. 符号链接
ln -s a.txt link.txt
符号链接本身经常显示为 777,但这个权限通常没有实际意义。真正起作用的是目标文件 a.txt 的权限。很多情况下,chmod 600 link.txt 实际修改的是目标文件 a.txt 的权限,而不是链接本身。
符号链接的显示权限通常不重要,真正重要的是目标文件权限。
十三、压缩和解压:tar 通常更能保留权限,zip 不一定
1. tar
tar -cf archive.tar mydir # 打包
tar -xf archive.tar # 解包
tar 会记录文件权限信息。但是解压时实际权限可能受到以下因素影响:当前用户权限、当前 umask、是否使用 root 解压、是否使用保留权限参数、文件系统是否支持权限、archive 内是否记录了属主属组。
如果想尽量保留权限,可以使用 tar --same-permissions -xf archive.tar。常见备份命令会用:
sudo tar --xattrs --acls -cpf backup.tar /some/dir
2. zip / unzip
zip 也可以保存一部分 Unix 权限信息,但它的跨平台属性更强。如果 zip 文件来自 Windows,里面可能没有完整的 Linux 权限信息。解压后经常出现可执行权限丢失等问题。
如果是在 Linux 系统之间备份、迁移文件,通常优先考虑 tar 或 rsync,而不是 zip。
十四、rsync:是否保留权限,关键看参数
普通用法:
rsync source.txt remote:/path/
这种情况下,权限可能受目标端 umask 影响。
更常见的是使用归档模式:
rsync -a source_dir/ target_dir/
-a 表示 archive,会尽量保留:权限、符号链接、时间戳、递归目录、属主属组(前提是有权限)。如果是 root 执行,保留信息更完整。
如果希望同步时调整权限,可以使用:
rsync -a --chmod=Du=rwx,Dgo=rx,Fu=rw,Fgo=r source/ target/
这里:
| 写法 | 含义 |
|---|---|
D |
directory,目录 |
F |
file,文件 |
u |
所有者 |
g |
所属组 |
o |
其他人 |
这个命令的意思大致是:目录 755,文件 644。适合部署网站、同步项目文件。
十五、scp / sftp:远程复制时,权限可能受远程 umask 影响
scp a.txt user@server:/path/
目标文件的权限可能受远程服务器的 umask 影响。如果想保留原文件的时间和权限,可以使用:
scp -p a.txt user@server:/path/
-p 表示 preserve,会保留修改时间、访问时间和权限模式。不过它对属主属组的保留能力有限,因为远程用户通常不能随意创建属于别人的文件。如果你需要更可靠地同步权限,通常建议使用 rsync -a,而不是普通 scp。
十六、git:不会完整保存 Linux 权限,只保存可执行位
很多人以为 Git 会完整保存文件权限,其实不是。Git 通常只关心:普通文件是否可执行,也就是大致区分 644 普通文件和 755 可执行文件。
chmod +x run.sh
git add run.sh
git commit -m "make run.sh executable"
Git 会记录它是可执行文件。但是 Git 不会完整记录:文件属主、文件属组、ACL、setuid、setgid、sticky bit、复杂权限组合。
如果你需要保存完整 Linux 权限,不应该只依赖 Git。
十七、ACL:会让权限变化比 chmod 更复杂
除了传统的 rwx 权限,Linux 还支持 ACL。
查看 ACL:getfacl a.txt
设置 ACL:setfacl -m u:bob:rw a.txt(给用户 bob 单独增加读写权限)
目录还可以设置默认 ACL:
setfacl -m d:g:developers:rwx project/
这表示在 project/ 目录中新建的文件或子目录,会继承某些 ACL 规则。
一旦目录设置了默认 ACL,新建文件的权限结果就不再只是简单的”默认权限 – umask”,而是会受到默认 ACL 影响。所以有时你会发现
touch a.txt生成的权限和你根据 umask 推算的不一样,这时就应该检查getfacl .和getfacl a.txt。
十八、setuid、setgid、sticky bit:特殊权限位也会受操作影响
1. setuid
显示为 -rwsr-xr-x。它主要用于可执行文件。当用户执行这个程序时,进程会临时获得文件所有者的身份。典型例子是 /usr/bin/passwd。这类权限非常敏感。复制、修改属主、普通用户写入文件时,系统可能会清除 setuid 位,防止安全风险。
2. setgid
对于文件,setgid 类似 setuid,但对应的是组身份。对于目录,setgid 更常见。例如 chmod g+s project,查看为 drwxrwsr-x project。这表示在 project 目录中新建的文件或目录,会倾向于继承 project 的属组。这在团队协作目录中很有用。
3. sticky bit
常见于 /tmp:drwxrwxrwt /tmp。它的作用是:即使目录所有人可写,用户也不能随便删除别人的文件。共享临时目录经常需要 sticky bit。设置方式:chmod +t shared_tmp 或 chmod 1777 shared_tmp。
十九、挂载不同文件系统:权限表现可能完全不同
如果文件位于 Linux 原生文件系统(如 ext4、xfs、btrfs),那么权限、属主、属组、ACL 等通常可以正常保存。但如果是 FAT32、exFAT、NTFS,情况就复杂了。
这些文件系统本身不一定按 Linux 的方式保存权限。于是 Linux 可能通过挂载参数”模拟”权限。例如:
mount -o uid=1000,gid=1000,fmask=0133,dmask=0022 /dev/sdb1 /mnt/usb
其中:
| 参数 | 含义 |
|---|---|
uid |
指定文件显示为哪个用户所有 |
gid |
指定文件显示为哪个组所有 |
fmask |
文件权限掩码 |
dmask |
目录权限掩码 |
所以在 U 盘、移动硬盘、Windows 分区上,你看到的权限未必是真实写入文件系统的权限,而可能是挂载时计算出来的显示结果。
二十、常见操作后的权限变化总结
| 操作 | 权限是否变化 | 主要规则 |
|---|---|---|
| touch 新文件 | 会产生新权限 | 受 umask 影响 |
| touch 已有文件 | 通常不变 | 只更新时间戳 |
| mkdir | 会产生新权限 | 目录默认 777 减 umask |
| echo > 新文件 | 会产生新权限 | 受 umask 影响 |
| echo > 已有文件 | 通常不变 | 只覆盖内容 |
| echo >> 已有文件 | 通常不变 | 只追加内容 |
| cp 到新文件 | 可能变化 | 参考源权限,但可能受 umask 和参数影响 |
| cp 覆盖已有文件 | 通常保留目标原权限 | 内容变,权限不一定变 |
| cp -p | 尽量保留 | 保留权限、时间戳等 |
| cp -a | 尽量完整保留 | 适合复制目录 |
| mv 同文件系统 | 不变 | 只是改名字或位置 |
| mv 跨文件系统 | 可能变化 | 类似复制再删除 |
| rm | 不改变权限 | 删除取决于父目录权限 |
| chmod | 改变 | 直接修改权限 |
| chown | 改变属主 | 可能清除特殊权限位 |
| chgrp | 改变属组 | 可能影响协作权限 |
| tar 解压 | 可能保留 | 受参数、umask、用户身份影响 |
| zip 解压 | 不一定保留 | 跨平台时容易丢失权限 |
| rsync -a | 尽量保留 | 同步目录推荐 |
| scp | 可能变化 | 受远程 umask 影响 |
| scp -p | 尽量保留模式和时间 | 但属主属组有限 |
| git clone | 不完整保留 | 主要保存可执行位 |
二十一、几个典型场景
场景一:为什么我新建的文件是 644,目录是 755?
因为你的 umask 很可能是 022。文件:666 – 022 = 644;目录:777 – 022 = 755。可以查看 umask,临时修改 umask 077 后新建文件和目录通常变成 600 和 700,适合更私密的环境。
场景二:为什么复制文件后权限没有完全一样?
因为普通 cp 不一定完整保留所有元数据。如果希望尽量保留权限,使用 cp -p file1 file2;复制目录时使用 cp -a dir1 dir2。
场景三:为什么我没有文件写权限,却能删除它?
因为删除文件看的是父目录权限。只要你对父目录有 w + x,就可能删除其中的文件。但如果目录有 sticky bit(例如 /tmp),就不能随便删除别人的文件。
场景四:为什么移动文件后权限没变?
如果是同一文件系统内 mv a.txt b.txt,这只是改名字,文件本身没变,所以权限不变。如果跨磁盘、跨分区、移动到 U 盘,就可能变。
场景五:为什么脚本从 Git 拉下来后不能执行?
可能是 Git 没记录可执行位,或者可执行位没有正确提交。可以执行 chmod +x script.sh 然后提交。但如果文件所在分区以 noexec 挂载,即使有 x 权限也不能直接执行。
二十二、实用检查命令
| 用途 | 命令 |
|---|---|
| 查看权限 | ls -l |
| 查看目录自身权限 | ls -ld dirname |
| 查看 inode | ls -li |
| 查看当前 umask | umask |
| 查看 ACL | getfacl filename |
| 查看挂载参数 | mount 或 findmnt |
| 查看文件系统类型 | df -T |
| 查看文件详细状态 | stat filename |
stat a.txt 会显示:Access(权限)、Uid、Gid、Modify、Change、Birth。其中 Change 是元数据变化时间,比如权限、属主、属组改变时会更新。
二十三、实用建议
日常使用中,可以记住几条经验:
- 新建文件的权限主要看 umask。
- 修改已有文件内容通常不改变权限。
- 复制文件不一定完整保留权限,想保留权限用 cp -p 或 cp -a。
- 同一文件系统内移动文件,权限通常不变。
- 删除文件主要看父目录权限,而不是文件自己的写权限。
- 目录的 x 权限非常关键,没有 x 就很难进入和访问。
- 压缩备份 Linux 文件时,优先考虑 tar 或 rsync -a。
- U 盘、NTFS、exFAT 分区上的权限可能是挂载参数模拟出来的。
- 团队协作目录可以考虑 setgid 和默认 ACL。
- 遇到权限异常时,不只看 ls -l,还要看 getfacl、stat、findmnt、umask。
结语
Linux 文件权限的变化并不是只有 chmod 才会发生。很多看似普通的操作,比如复制、解压、同步、远程传输、跨分区移动,都会影响最终权限。
最核心的判断思路是:
- 如果是新建对象:看 umask、默认 ACL、挂载参数。
- 如果是修改已有文件:权限通常不变。
- 如果是复制或迁移:看命令参数是否保留元数据。
- 如果是删除或重命名:看父目录权限。
- 如果权限表现异常:检查 ACL、特殊权限位和文件系统挂载方式。
掌握这套逻辑后,再遇到”为什么这个文件权限变了”或”为什么我删不掉/执行不了/访问不了”这类问题,就能比较快地定位原因。












暂无评论内容