You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:43:21