| 文件系統 | 支持 Unix 權限 (rwx/uid/gid) | 典型場景 |
| ext4 / xfs / btrfs | ✅ 完整支持 | Linux 系統盤、數據盤 |
| FAT32 / exFAT / NTFS (Linux 掛載默認) | ❌ 不支持 / 部分支持 | U 盤、移動硬盤、雙系統共享盤 |
當 cp src.sh /media/usb/ 複製到 FAT32 時:
- 源文件 inode 包含 mode (rwxr-xr-x)、uid、gid、mtime 等屬性。
- 目標文件系統無 inode 概念,無法存儲 mode/uid/gid。
- 驅動程序按默認掛載選項(如
uid=1000,gid=1000,umask=022)創建目標文件,所有文件統一權限(通常 644 或 755)。
- 拷回 ext4 時,只能讀取到目標文件系統呈現的屬性,原始執行位丟失。
cp 命令的複製機制
cp [選項] 源 目標
--preserve[=屬性列表] # 保留屬性:mode,ownership,timestamps,links,context,xattr,all
-p # 等同 --preserve=mode,ownership,timestamps
-a # 歸檔模式 = -dR --preserve=all(遞歸+保留所有+保留鏈接)
關鍵點:--preserve 只能保留「目標文件系統支持」的屬性。FAT32 不支持 mode/ownership,故權限必丟。
實戰保留方案
方案一:打包壓縮保留元數據(推薦)
# 打包保留所有屬性
tar -czvf script.tar.gz script.sh
# 拷貝 tar.gz 到 U 盤(普通文件,無權限問題)
# 還原時自動恢復權限、所有者、時間戳
tar -xzvf script.tar.gz
優點:跨平台、單文件傳輸、完整保留 Unix 語義。
方案二:使用支持 Unix 權限的文件系統
- U 盤格式化為 ext4(僅 Linux 間使用)或 NTFS(配合
ntfs-3g 掛載選項 uid=1000,gid=1000,umask=000,permissions)。
- rsync 同步:
rsync -avz src/ /mnt/ntfs_disk/ 可保留權限。
方案三:拷貝後手動恢復(臨時補救)
chmod +x script.sh # 恢復執行權限
chown user:group script.sh # 恢復所有者(需 root)
方案四:Git 版本控制(代碼/腳本專用)
git add script.sh; git commit -m "keep perms"
# Git 索引記錄 mode 100755/100644,克隆後自動恢復
進階:cp --preserve 實戰測試
touch test.sh; chmod 700 test.sh
cp --preserve=mode test.sh /tmp/ext4_test.sh # ext4 目標:權限保留 700
cp --preserve=mode test.sh /media/usb/test.sh # FAT32 目標:權限變為掛載默認 (如 755)
總結
- 權限丟失本質是目標文件系統語義缺失,非 cp 命令缺陷。
- 跨 FAT32/exFAT 傳輸必須打包 或改用支持 Unix 權限的文件系統。
- 日常開發納入 Git 管理,天然解決權限保留與版本追溯。
理解文件系統層面的語義差異,能讓你在異構存儲間遷移數據時游刃有餘。
- 上一篇文章: C/C++ 內存管理:new 動態分配與 strcpy 與指針賦值的本質區別
- 下一篇文章: GitHub 與開源協作:徹底搞懂 Fork 與 Forks 的含義
Copyright ©
程式碼之家 All Rights Reserved