检查 SFTP 服务器上的文件是否为符号 link,并使用 Python Paramiko/pysftp 删除符号 link

Checking if a file on SFTP server is a symbolic link, and deleting the symbolic link, using Python Paramiko/pysftp

我在基于 linux 的服务器上有一个目录,其中包含子目录,其中一个包含指向服务器上其他地方的另一个目录的符号 link。

我想使用 python 脚本,从网络上的 Windows 计算机远程删除目录及其所有内容。这样做时,我想删除符号 link,但 而不是 删除符号 link 指向的目录或其任何内容。

这是我的代码(部分取自另一个 Whosebug 答案 ):

def rm_tree(remote_path, connection):
    """Recursively remove a remote directory and all its contents

    The remote server must have a POSIX-standard file system

    Parameters
    ----------
    remote_path : str
        Directory on the remote server to remove
    connection : pysftp.Connection
        Connection to the remote server on which to find the directory

    Returns
    -------
    None
    """
    # 
    try:
        files = connection.listdir(remote_path)
    except FileNotFoundError:
        files = []
    for filename in files:
        rpath = posixpath.join(remote_path, filename)
        if connection.isdir(rpath):
            rm_tree(rpath, connection)
        else:
            connection.unlink(rpath)
    with contextlib.suppress(FileNotFoundError):
        connection.rmdir(remote_path)

当我 运行 收到来自 paramiko 的错误时,信息很少,它是一个 IOError,消息为“OSError: Failure”。当它试图删除包含符号 link 的目录时,它在我的函数 connection.rmdir(remote_path) 的最后一行给出了该错误。该函数已删除目录的剩余内容,但符号 link 仍然存在。

我认为我需要添加到我的函数中的是:

if is_symlink(rpath):
   remove_symlink(rpath)

在检查它是否是目录之前,但我在 pysftp 或 paramiko 文档中找不到任何与 is_symlinkremove_symlink 函数等效的内容。

如何确定远程文件是否为符号 link,以及如何远程删除符号 links?

不要使用 Connection.listdirConnection.isdir。那是低效的。使用 Connection.listdir_attr 检索包含所有属性的列表。 请注意 Connection.listdir 内部调用 Connection.listdir_attr 并丢弃属性。

有了这些属性,您可以使用stat.S_ISLNK来确定条目是否是符号链接。

import stat
for f in connection.listdir_attr(remote_path):
    rpath = posixpath.join(remote_path, f.filename)
    if stat.S_ISLNK(f.st_mode)):
        connection.unlink(rpath)
    elif stat.S_ISDIR(f.st_mode):
        rm_tree(rpath, connection)
    else:
        connection.unlink(rpath)