Renci SSH.NET:如何删除非空目录?

7

我正在使用Renci SSH.NET访问Unix服务器上的文件和文件夹。 我想通过指定基本目录来删除整个目录树,但是当我调用sftp.DeleteDirectory(destination)时,只有传递空目录才能成功。

然而,我也想能够删除包含文件或其他文件夹的目录。 大多数.NET类将自动处理此操作,如何在SSH.NET中实现?

3个回答

17

SSH.NET库不支持任何递归操作,因此也不提供递归删除功能。

您需要使用SftpClient.ListDirectory方法递归列出所有文件和子文件夹并逐个删除它们。

private static void DeleteDirectory(SftpClient client, string path)
{
    foreach (SftpFile file in client.ListDirectory(path))
    {
        if ((file.Name != ".") && (file.Name != ".."))
        {
            if (file.IsDirectory)
            {
                DeleteDirectory(client, file.FullName);
            }
            else
            {
                client.DeleteFile(file.FullName);
            }
        }
    }

    client.DeleteDirectory(path);
}

或者使用另一个SFTP库。

例如,使用WinSCP的.NET程序集,您可以使用Session.RemoveFiles方法来递归删除目录。

// Setup session options
SessionOptions sessionOptions = new SessionOptions
{
    Protocol = Protocol.Sftp,
    HostName = "example.com",
    UserName = "user",
    Password = "mypassword",
    SshHostKeyFingerprint = "ssh-rsa 2048 xxxxxxxxxxx...="
};

using (Session session = new Session())
{
    // Connect
    session.Open(sessionOptions);

    // Delete the directory recursively
    session.RemoveFiles("/directory/to/delete").Check();
}

WinSCP GUI可以为您生成代码模板

(我是WinSCP的作者)


3

尝试在SSH中执行命令而不是使用sftp rm -rf 或者 rm -r。

代码可能如下所示:

Renci.SshClient ssh1 = new SshCLient("server","user","password");
ssh1.connect();
ssh1.RunCommand("cd LandingZone;rm -rf <directoryName>");
ssh1.Disconnect();

-2

您可以使用SSH.NET库动态地删除目录树或文件(无论是空目录还是非空目录),只需使用以下两种方法指定远程路径:

  public bool DeleteRemoteDirectoryRecursive(string RemoteDirectoryPath)
  {
        if (string.IsNullOrEmpty(RemoteDirectoryPath))
        {                
            return false;
        }

        var ConnectionInfo = new ConnectionInfo(this.sftpHost, this.sftpPort, this.sftpUser, new PasswordAuthenticationMethod(this.sftpUser, this.sftpPassword));
        using (var client = new SftpClient(ConnectionInfo))
        {                
            client.Connect();

            if (!client.Exists(RemoteDirectoryPath))
            {                   
                client.Disconnect();
                client.Dispose();
                return false;
            }

            foreach (var file in client.ListDirectory(RemoteDirectoryPath))
            {
                if (file.Name.Equals(".") || file.Name.Equals(".."))
                    continue;

                if (file.IsDirectory)
                {
                    client.Disconnect();
                    DeleteRemoteDirectoryRecursive(file.FullName);
                }
                else
                    client.DeleteFile(file.FullName);
            }

            client.DeleteDirectory(RemoteDirectoryPath);

        }

        return true;
    }

    public bool Remove(string RemotePath)
    {
        bool ReturnResult = false;

        try
        {
            if (string.IsNullOrEmpty(RemotePath))
            {
                return false;
            }

            var ConnectionInfo = new ConnectionInfo(this.sftpHost, this.sftpPort, this.sftpUser, new PasswordAuthenticationMethod(this.sftpUser, this.sftpPassword));
            using (var client = new SftpClient(ConnectionInfo))
            {
                client.Connect();

                if (!client.Exists(RemotePath))
                {
                    client.Disconnect();
                    client.Dispose();
                    return false;
                }

                try
                {
                    //  path is directory
                    client.ChangeDirectory(RemotePath);
                    try
                    {
                        DeleteRemoteDirectoryRecursive(RemotePath);
                        ReturnResult = true;
                    }
                    catch
                    {
                        ReturnResult = false;
                    }

                }
                // path is a file
                catch
                {
                    try
                    {
                        client.DeleteFile(RemotePath);
                        ReturnResult = true;
                    }
                    catch
                    {
                        ReturnResult = false;
                    }
                }
            }
        }
        catch (Exception ex)
        {                
            ReturnResult = false;
        }
        return ReturnResult;
    }

2
虽然你的代码可能能够工作,但它非常低效 - 你为每个目录都打开了一个新连接。 - Martin Prikryl
2
此外,为什么您在Remove方法中使用ChangeDirectory来测试条目是文件还是目录?为什么不像DeleteRemoteDirectoryRecursive方法中那样使用file.IsDirectory呢? - Martin Prikryl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接