Renci SSH.NET:是否可以创建包含不存在的子文件夹的文件夹

Eri*_*rik 3 c# ssh recursion sftp ssh.net

我目前正在使用Renci SSH.NET使用SFTP将文件和文件夹上传到Unix服务器,并使用创建目录

sftp.CreateDirectory("//server/test/test2");
Run Code Online (Sandbox Code Playgroud)

只要文件夹"test"已经存在,它就能完美运行.如果没有,则该CreateDirectory方法失败,并且每次尝试创建包含多个级别的目录时都会发生这种情况.

是否有一种优雅的方式来递归生成字符串中的所有目录?我假设该CreateDirectory方法自动完成.

Mar*_*ryl 10

别无他法.

只需迭代目录级别,使用测试每个级别SftpClient.GetAttributes并创建不存在的级别.

static public void CreateDirectoryRecursively(this SftpClient client, string path)
{
    string current = "";

    if (path[0] == '/')
    {
        path = path.Substring(1);
    }

    while (!string.IsNullOrEmpty(path))
    {
        int p = path.IndexOf('/');
        current += '/';
        if (p >= 0)
        {
            current += path.Substring(0, p);
            path = path.Substring(p + 1);
        }
        else
        {
            current += path;
            path = "";
        }

        try
        {
            SftpFileAttributes attrs = client.GetAttributes(current);
            if (!attrs.IsDirectory)
            {
                throw new Exception("not directory");
            }
        }
        catch (SftpPathNotFoundException)
        {
            client.CreateDirectory(current);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 8

Martin Prikryl提供的代码略有改进

不要将Exceptions用作流控制机制.这里更好的选择是先检查当前路径是否存在.

if (client.Exists(current))
{
    SftpFileAttributes attrs = client.GetAttributes(current);
    if (!attrs.IsDirectory)
    {
        throw new Exception("not directory");
    }
}
else
{
    client.CreateDirectory(current);
}
Run Code Online (Sandbox Code Playgroud)

而不是try catch构造

try
{
    SftpFileAttributes attrs = client.GetAttributes(current);
    if (!attrs.IsDirectory)
    {
        throw new Exception("not directory");
    }
}
catch (SftpPathNotFoundException)
{
    client.CreateDirectory(current);
}
Run Code Online (Sandbox Code Playgroud)

  • 另外值得一提的是,您的代码效率较低,因为每个目录级别需要两次往返服务器.注意`.Exists`是如何实现的.在内部,它完全符合我的原始代码.它调用`.GetAttributes`并返回`true`如果它不抛出.如果抛出,它会捕获`SftpPathNotFoundException`并返回`false`.所以你似乎只是避免使用控制流的异常.这就是为什么我选择一个带有单个调用的变体和`try` ...`catch`结构.如果服务器的延迟很大,您将会有所不同.+1反正:) (3认同)
  • +不要将答案基于现有答案.你的答案必须独立.所以请包含完整的代码,而不是说"在代码中使用此代替".当然,预计会承认代码的来源. (2认同)

小智 5

嗨,我发现我的答案很直接。自从我发现这篇旧帖子后,我想其他人也可能会偶然发现它。接受的答案不太好,所以这是我的看法。它没有使用任何计数技巧,所以我认为它更容易理解一点。

public void CreateAllDirectories(SftpClient client, string path)
    {
        // Consistent forward slashes
        path = path.Replace(@"\", "/");
        foreach (string dir in path.Split('/'))
        {
            // Ignoring leading/ending/multiple slashes
            if (!string.IsNullOrWhiteSpace(dir))
            {
                if(!client.Exists(dir))
                {
                    client.CreateDirectory(dir);
                }
                client.ChangeDirectory(dir);
            }
        }
        // Going back to default directory
        client.ChangeDirectory("/");
    }
Run Code Online (Sandbox Code Playgroud)