python 使用Paramiko递归目录下载?

zi8p0yeb  于 2022-12-10  发布在  Python
关注(0)|答案(8)|浏览(203)

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

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

mitkmikd

mitkmikd1#

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

6mzjoqzu

6mzjoqzu2#

一个老问题,但我想出了一个解决方案,工作得很好,它有点草率(类型转换和斜杠和所有)-但它确实工作。
请注意,这将使用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)
z18hc3ub

z18hc3ub3#

Paramiko不支持递归操作。
但它很容易实现:
第一个
你也可以使用pysftp,它是一个Paramiko的 Package 器,有更多Python风格的外观和感觉,并且支持递归操作。

  • pysftp.Connection.put_r()
  • pysftp.Connection.get_r()

或者看看我对Python pysftp get_r from Linux的回答,它在Linux上运行良好,但在Windows上却不行。
但是pysftp似乎是一个被放弃的项目,所以你最好坚持使用Paramiko。

hxzsmxv2

hxzsmxv24#

丹·拉曼纳的答案在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()
xriantvc

xriantvc6#

stat()方法和其他属性返回权限。d(例如drwxrwxrwx)显示它是目录。
例如:

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

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

mwg9r5ms

mwg9r5ms7#

2022年的答案在这里。
pysftp被放弃了。paramiko没有实现SFTP的递归性。所以我基于Paramiko做了一个名为sftputil的库(与ftputil并行)。
sftputil实现了walkglobsync等功能。要复制整个目录,最简单的方法是使用同步功能:

from sftputil import SFTP

sftp = SFTP("hostname", "username", password="password")

# To copy recursively
sftp.sync_pull("remote/path", "local/dir")

# To copy only the files
sftp.sync_pull("remote/path", "local/dir", recursive=False)
kb5ga3dv

kb5ga3dv8#

如果你使用Linux或类Unix。你可以使用'文件'实用程序与popen。或者简单的u可以使用os.path.isdir()=)

相关问题