.NET Core 3.0中如何同步两个文件/目录权限?自动更新程序问题
这个坑我之前踩过!问题出在你用的GetAccessControl和SetAccessControl是Windows专属的API,完全不兼容macOS的权限模型。
为什么会抛出NotSupportedException?
.NET的GetAccessControl/SetAccessControl方法是为Windows NTFS文件系统的ACL(访问控制列表)设计的,而macOS采用的是POSIX权限体系(也就是我们常说的rwxr-xr-x那种),还有一套自己的扩展ACL机制,但.NET的这套API在非Windows平台上根本没有实现,所以调用时会直接抛出异常。
正确的解决方案
根据你使用的.NET版本,有两种靠谱的解决方式:
方式一:用.NET Core 3.0+的原生Unix权限API(推荐)
从.NET Core 3.0开始,官方提供了专门针对Unix-like系统的权限操作API,完全不需要调用外部命令:
同步单个文件的权限
// 获取旧文件的POSIX权限 var oldFilePerms = File.GetUnixFilePermissions(oldFilePath); // 应用到新文件 File.SetUnixFilePermissions(newFilePath, oldFilePerms);
同步单个目录的权限
var oldDirPerms = Directory.GetUnixFilePermissions(oldDirPath); Directory.SetUnixFilePermissions(newDirPath, oldDirPerms);
递归同步目录下所有内容的权限
如果需要同步整个目录树的权限,可以写个递归方法:
void SyncDirectoryPermissions(string oldDir, string newDir) { // 同步当前目录权限 var dirPerms = Directory.GetUnixFilePermissions(oldDir); Directory.SetUnixFilePermissions(newDir, dirPerms); // 同步子目录 foreach (var subOldDir in Directory.GetDirectories(oldDir)) { var subNewDir = Path.Combine(newDir, Path.GetFileName(subOldDir)); if (Directory.Exists(subNewDir)) { SyncDirectoryPermissions(subOldDir, subNewDir); } } // 同步文件 foreach (var oldFile in Directory.GetFiles(oldDir)) { var newFile = Path.Combine(newDir, Path.GetFileName(oldFile)); if (File.Exists(newFile)) { var filePerms = File.GetUnixFilePermissions(oldFile); File.SetUnixFilePermissions(newFile, filePerms); } } }
方式二:调用macOS系统命令(兼容旧.NET版本)
如果你还在使用.NET Framework或者低于3.0的.NET Core,可以通过调用stat和chmod命令来实现:
using System.Diagnostics; // 辅助方法:获取文件/目录的8进制权限字符串 string GetUnixPermissions(string path) { var process = new Process { StartInfo = new ProcessStartInfo { FileName = "stat", // -f %p 输出8进制权限(比如755、644) RedirectStandardOutput = true, UseShellExecute = false, CreateNoWindow = true } }; // 用ArgumentList避免路径空格转义问题 process.StartInfo.ArgumentList.Add("-f"); process.StartInfo.ArgumentList.Add("%p"); process.StartInfo.ArgumentList.Add(path); process.Start(); var permStr = process.StandardOutput.ReadToEnd().Trim(); process.WaitForExit(); return permStr; } // 辅助方法:设置文件/目录的权限 void SetUnixPermissions(string path, string permissions) { var process = new Process { StartInfo = new ProcessStartInfo { FileName = "chmod", UseShellExecute = false, CreateNoWindow = true } }; process.StartInfo.ArgumentList.Add(permissions); process.StartInfo.ArgumentList.Add(path); process.Start(); process.WaitForExit(); } // 使用示例 var oldPerms = GetUnixPermissions(oldPath); SetUnixPermissions(newPath, oldPerms);
额外提示:针对Shell脚本的可执行权限
如果你只需要确保新脚本和旧脚本有相同的可执行权限,也可以单独判断:
var oldPerms = File.GetUnixFilePermissions(oldScriptPath); // 检查是否包含任意可执行权限 var hasExecutePerm = (oldPerms & UnixFilePermissions.UserExecute) != 0 || (oldPerms & UnixFilePermissions.GroupExecute) != 0 || (oldPerms & UnixFilePermissions.OtherExecute) != 0; if (hasExecutePerm) { // 给新脚本加上可执行权限(保留原有读写权限) var newPerms = File.GetUnixFilePermissions(newScriptPath); File.SetUnixFilePermissions(newScriptPath, newPerms | oldPerms & (UnixFilePermissions.UserExecute | UnixFilePermissions.GroupExecute | UnixFilePermissions.OtherExecute)); }
内容的提问来源于stack exchange,提问作者candycat
相关产品推荐
相关产品推荐

