【问题标题】:Recursive file list with FTP使用 FTP 的递归文件列表
【发布时间】:2020-12-03 09:36:20
【问题描述】:

我知道如何从 FTP 服务器列出目录中的所有文件:

import ftplib
ftp = ftplib.FTP()
ftp.connect("192.168.1.18", port=2240)
ftp.login()
ftp.cwd('path/to')
for f in ftp.mlsd():
    print(f)

但获取递归文件列表(即子目录、子子目录等中的文件)的最佳方法是什么?

即Python 3 的 glob.glob('path/to/**/*', recursive=True) 的 FTP 等效项,它递归地列出所有文件。

我可以手动输入每个目录,然后重做msld(),但我担心这会很慢(据我记忆,在 FTP 中列出文件已经很慢了),所以这不是最佳选择。

如何使用 SFTP 来做到这一点?使用 SFTP 递归列出所有文件会更容易吗?

【问题讨论】:

    标签: python ftp ftplib


    【解决方案1】:

    由于LIST -RNLST -RMLSD -R 对我不起作用,我遵循@MartinPrikryl 的建议,这是一个 FTP 解决方案:

    import ftplib, time
    def list_recursive(ftp, remotedir):
        ftp.cwd(remotedir)
        for entry in ftp.mlsd():
            if entry[1]['type'] == 'dir':
                remotepath = remotedir + "/" + entry[0]
                print(time.time() - t0, remotepath)
                list_recursive(ftp, remotepath)
            else:
                print(entry)
    ftp = ftplib.FTP()
    ftp.connect("192.168.1.18", port=2240)
    ftp.login()
    t0 = time.time()
    list_recursive(ftp, '/sdcard/music')
    

    大约 900 个文件夹中的大约 20k 个文件需要 344 秒(我的 FTP 服务器在手机上:cx File Explorer 应用程序)。


    作为比较,这里有一个 SFTP 的解决方案:

    import pysftp
    def list_recursive(sftp, remotedir):
        for entry in sftp.listdir_attr(remotedir):
            remotepath = remotedir + "/" + entry.filename
            if sftp.isdir(remotepath):
                print(remotepath)            
                list_recursive(sftp, remotepath)
            else:
                print(entry.st_size, entry.st_mtime, entry.filename)
    cnopts = pysftp.CnOpts()  # for local testing
    cnopts.hostkeys = None 
    with pysftp.Connection('192.168.1.18', port=2222, username='ssh', password='', cnopts=cnopts) as sftp:
        list_recursive(sftp, 'music')
    

    大约 900 个文件夹中的大约 20k 个文件花费了 222 秒(我在 Android 手机上使用了 SSH/SFTP Server 应用程序)。

    【讨论】:

    • +1 – 尽管有一个强制性警告:请勿设置cnopts.hostkeys = None,除非您不关心安全性。见Verify host key with pysftp
    【解决方案2】:

    我可以手动输入每个目录,然后重做一个 msld()

    这是正确的解决方案。 FTP 协议没有更好的标准 方法来检索递归列表。所以没有优化的空间(只能通过并行化操作)。另见Downloading a directory tree with ftplib

    一些 FTP 服务器支持带有一些文件列表命令的非标准 -R 开关(不确定 MLSD)。因此,如果您愿意依赖非标准功能并且您的特定服务器支持它,您可以通过这种方式优化您的代码。另见Getting all FTP directory/file listings recursively in one call

    对于 SFTP,请参阅Recursive SFTP listdir in Python?

    【讨论】:

      猜你喜欢
      • 2018-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-07
      • 1970-01-01
      相关资源
      最近更新 更多