代码之家  ›  专栏  ›  技术社区  ›  Shiva Krishna Bavandla

如何在Python中通过SFTP连接后列出目录中的所有文件夹和文件

  •  47
  • Shiva Krishna Bavandla  · 技术社区  · 12 年前

    我正在使用Python,并试图连接到SFTP,希望从那里检索一个XML文件,并需要将其放置在我的本地系统中。以下是代码:

    import paramiko
    
    sftpURL   =  'sftp.somewebsite.com'
    sftpUser  =  'user_name'
    sftpPass  =  'password'
    
    ssh = paramiko.SSHClient()
    # automatically add keys without requiring human intervention
    ssh.set_missing_host_key_policy( paramiko.AutoAddPolicy() )
    
    ssh.connect(sftpURL, username=sftpUser, password=sftpPass)
    
    ftp = ssh.open_sftp()
    files = ftp.listdir()
    print files
    

    这里的连接是成功的全部。现在,我想查看所有的文件夹和文件,并需要输入所需的文件夹,以便从中检索XML文件。

    最后,我的意图是在连接到SFTP服务器后查看所有文件夹和文件。

    在上面的代码中,我使用了 ftp.listdir() 通过它我得到了如下的输出

    ['.bash_logout', '.bash_profile', '.bashrc', '.mozilla', 'testfile_248.xml']
    

    我想知道是否只有这些文件?

    我上面使用的命令也可以查看文件夹吗?

    查看所有文件夹和文件的命令是什么?

    3 回复  |  直到 5 年前
        1
  •  47
  •   Martin Prikryl    3 年前

    这个 SFTPClient.listdir 返回所有内容、文件和文件夹。

    如果有文件夹,要将它们与文件区分开来,请使用 SFTPClient.listdir_attr 相反它返回的集合 SFTPAttributes

    from stat import S_ISDIR, S_ISREG
    
    sftp = ssh.open_sftp()
    
    for entry in sftp.listdir_attr(remotedir):
        mode = entry.st_mode
        if S_ISDIR(mode):
            print(entry.filename + " is folder")
        elif S_ISREG(mode):
            print(entry.filename + " is file")
    

    @Oz123的公认答案是低效的。 SFTP客户端.listdir 内部调用 SFTP客户端.listdir_attr 并且只丢弃返回文件和文件夹名称的大部分信息。然后,答案通过调用 SFTPClient.lstat 对于每个文件。

    另请参阅 How to fetch sizes of all SFTP files in a directory through Paramiko


    强制性警告:请勿使用 AutoAddPolicy 你正在失去保护 MITM attacks 这样做。有关正确的解决方案,请参阅 Paramiko "Unknown Server"

        2
  •  17
  •   oz123    12 年前

    一个快速的解决方案是检查 lstat 中每个对象的 ftp.listdir()

    以下是列出所有目录的方法。

    >>> for i in ftp.listdir():
    ...     lstatout=str(ftp.lstat(i)).split()[0]
    ...     if 'd' in lstatout: print i, 'is a directory'
    ... 
    

    文件是相反的搜索:

    >>> for i in ftp.listdir():
    ...     lstatout=str(ftp.lstat(i)).split()[0]
    ...     if 'd' not in lstatout: print i, 'is a file'
    ... 
    
        3
  •  3
  •   scientific_explorer    4 年前

    这是我想出的一个解决方案。基于 https://stackoverflow.com/a/59109706 。我的解决方案给出了不错的结果。

    使现代化 我对它稍作修改,以采纳马丁的建议。现在,与使用 isdir listdir

    # prefix components:
    space =  '    '
    branch = '│   '
    # pointers:
    tee =    '├── '
    last =   '└── '
    
    def stringpath(path):
        # just a helper to get string of PosixPath
        return str(path)
    
    from pathlib import Path
    from stat import S_ISDIR
    def tree_sftp(sftp, path='.', parent='/', prefix=''):
        """
        Loop through files to print it out
        for file in tree_sftp(sftp):
            print(file)
        """
        fullpath = Path(parent, path)
        strpath = stringpath(fullpath)
    
        dirs = sftp.listdir_attr(strpath)
        pointers = [tee] * (len(dirs) - 1) + [last]
        pdirs = [Path(fullpath, d.filename) for d in dirs]
        sdirs = [stringpath(path) for path in pdirs]
    
        for pointer, sd, d in zip(pointers, sdirs, dirs):
            yield prefix + pointer + d.filename
            if S_ISDIR(d.st_mode):
                extension = branch if pointer == tee else space
                yield from tree_sftp(sftp, sd, prefix=prefix + extension)
    

    你可以这样试试 pysftp

    import pysftp
    with pysftp.Connection(HOSTNAME, USERNAME, PASSWORD) as sftp:
        for file in tree_sftp(sftp):
            print(file)
    

    如果if对你有效,请告诉我。