使用Paramiko进行递归目录下载?

13 投票
8 回答
23595 浏览
提问于 2025-04-16 21:24

我想通过SSH下载一个内容未知的目录,并且一直在尝试使用Paramiko。我看到过一些关于如何上传目录的例子,但没有找到关于递归下载的例子。

我可以列出目录中的所有项目,但还没有找到判断某个项目是文件(可以下载)还是目录(需要递归调用)的方法。

transport = paramiko.Transport((MY_IP, 22))
transport.connect(username=MY_NAME, password=MY_PASS)
sftp = paramiko.SFTPClient.from_transport(transport)

file_list = sftp.listdir(path='/home/MY_HOME_DIR')
    for item in file_list:
        # Here is an item name... but is it a file or directory?
        print(item)
sftp.close()
transport.close()

那么我怎么知道一个项目是文件还是目录呢?

8 个回答

3

这是一个老问题,但我想出了一个解决办法,效果还不错。虽然有点儿不够规范(比如类型转换和斜杠之类的),但确实能用。

请注意,这里使用了 fabric.api.local 来在目标位置创建目录。

def sftp_get_recursive(path, dest, sftp=sftp):
    item_list = sftp.listdir(path)
    dest = str(dest)

    if not os.path.isdir(dest):
        local("mkdir %s" % dest)

    for item in item_list:
        item = str(item)

        if is_directory(path + "/" + item, sftp):
            sftp_get_recursive(path + "/" + item, dest + "/" + item, sftp)
        else:
            sftp.get(path + "/" + item, dest + "/" + item)
4

Paramiko不支持递归操作。

不过,自己实现这个功能其实很简单:

import os
from stat import S_ISDIR, S_ISREG
def get_r_portable(sftp, remotedir, localdir):
    for entry in sftp.listdir_attr(remotedir):
        remotepath = remotedir + "/" + entry.filename
        localpath = os.path.join(localdir, entry.filename)
        mode = entry.st_mode
        if S_ISDIR(mode):
            try:
                os.mkdir(localpath)
            except OSError:     
                pass
            get_r_portable(sftp, remotepath, localpath)
        elif S_ISREG(mode):
            sftp.get(remotepath, localpath)

你也可以使用pysftp。它是一个封装了Paramiko的库,看起来更像Python的风格,并且支持递归操作。你可以查看:

或者你可以看看我对Python pysftp在Linux上正常工作,但在Windows上不行的回答

不过,pysftp似乎是一个被遗弃的项目,所以你最好还是继续使用Paramiko。

12
from stat import S_ISDIR

def isdir(path):
  try:
    return S_ISDIR(sftp.stat(path).st_mode)
  except IOError:
    #Path does not exist, so by definition not a directory
    return False

...假设 sftp 是一个已经打开的 Paramiko SFTP 连接。

撰写回答