12

我想通过 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()

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

4

7 回答 7

11
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 连接。

于 2011-11-29T08:08:10.753 回答
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)
于 2013-04-10T17:12:30.993 回答
2

Dan LaManna 的答案的一个小更新,适用于 2021 年。

import paramiko
import os
from stat import S_ISDIR, S_ISREG    

def sftp_get_recursive(path, dest, sftp):
    item_list = sftp.listdir_attr(path)
    dest = str(dest)
    if not os.path.isdir(dest):
        os.makedirs(dest, exist_ok=True)
    for item in item_list:
        mode = item.st_mode
        if S_ISDIR(mode):
            sftp_get_recursive(path + "/" + item.filename, dest + "/" + item.filename, sftp)
        else:
            sftp.get(path + "/" + item.filename, dest + "/" + item.filename)

transport = paramiko.Transport((host, port))
transport.connect(username=username, password=password)
sftp = paramiko.SFTPClient.from_transport(transport)
sftp_get_recursive(remote_path, local_path, sftp)
sftp.close()
于 2021-10-20T07:01:37.717 回答
2

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 get_r from Linux 的回答在 Linux 上运行良好,但在 Windows 上运行良好

但是 pysftp 似乎是一个废弃的项目,所以你最好坚持使用 Paramiko。

于 2018-11-30T10:58:56.367 回答
1

stat() 方法以及其他属性返回权限。d(例如 drwxrwxrwx)表明它是目录。

例如:

dir = oct(sftp.stat(path).st_mode)
print dir[0:2]

输出解释: 01 fifo 02 字符特殊 04 目录 06 块特殊 10 常规文件 12 符号链接 14 套接字

于 2012-03-14T07:44:47.923 回答
1

您可以使用 sftp 对象的 stat() 方法:

http://www.lag.net/paramiko/docs/paramiko.SFTPClient-class.html

于 2011-07-13T12:05:38.520 回答
-6

如果你使用 Linux 或类 Unix。您可以使用带有 popen 的“文件”实用程序。或者简单的你可以使用 os.path.isdir() =)

于 2011-07-13T08:15:25.580 回答