遍历FTP列表

2024-05-14 18:46:18 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图从FTP服务器获取所有目录的名称,并将它们按层次顺序存储在多维列表或dict中

例如,包含以下结构的服务器:

/www/
    mysite.com
        images
            png
            jpg

在剧本的结尾,会给我一个清单,比如

['/www/'
  ['mysite.com'
    ['images'
      ['png'],
      ['jpg']
    ]
  ]
]

我试过使用这样的递归函数: 定义遍历(dir): FTP.dir(目录,遍历)

FTP.dir返回以下格式的行:

drwxr-xr-x    5 leavesc1 leavesc1     4096 Nov 29 20:52 mysite.com

这样做行[56:]只会给出目录名(mysite.com)。我在递归函数中使用这个。

但我不能让它工作。我尝试了很多不同的方法,但都没成功。还有很多FTP错误(要么找不到目录-这是一个逻辑问题,有时服务器返回意外错误,这将不留下日志,我无法调试)

底线问题: 如何从FTP服务器获取层次目录列表?


Tags: 服务器目录名称com列表pngwww错误
3条回答

这是对我有用的Python 3脚本的初稿。它比调用cwd()快得多。传入服务器、端口、目录、用户名和密码作为参数。我把输出作为一个列表留给读者作为练习。

import ftplib
import sys

def ftp_walk(ftp, dir):
    dirs = []
    nondirs = []
    for item in ftp.mlsd(dir):
        if item[1]['type'] == 'dir':
            dirs.append(item[0])
        else:
            nondirs.append(item[0])
    if nondirs:
        print()
        print('{}:'.format(dir))
        print('\n'.join(sorted(nondirs)))
    else:
        # print(dir, 'is empty')
        pass
    for subdir in sorted(dirs):
        ftp_walk(ftp, '{}/{}'.format(dir, subdir))

ftp = ftplib.FTP()
ftp.connect(sys.argv[1], int(sys.argv[2]))
ftp.login(sys.argv[4], sys.argv[5])
ftp_walk(ftp, sys.argv[3])

这是一个天真而缓慢的实现。它很慢,因为它试图CWD到每个目录条目,以确定它是一个目录还是一个文件,但这是有效的。可以通过解析LIST命令输出来优化它,但这与服务器实现密切相关。

import ftplib

def traverse(ftp, depth=0):
    """
    return a recursive listing of an ftp server contents (starting
    from the current directory)

    listing is returned as a recursive dictionary, where each key
    contains a contents of the subdirectory or None if it corresponds
    to a file.

    @param ftp: ftplib.FTP object
    """
    if depth > 10:
        return ['depth > 10']
    level = {}
    for entry in (path for path in ftp.nlst() if path not in ('.', '..')):
        try:
            ftp.cwd(entry)
            level[entry] = traverse(ftp, depth+1)
            ftp.cwd('..')
        except ftplib.error_perm:
            level[entry] = None
    return level

def main():
    ftp = ftplib.FTP("localhost")
    ftp.connect()
    ftp.login()
    ftp.set_pasv(True)

    print traverse(ftp)

if __name__ == '__main__':
    main()

你不会喜欢这样,但是“它取决于服务器”,或者更准确地说,“它取决于服务器的输出格式”。

可以将不同的服务器设置为显示不同的输出,因此在一般情况下,您的初始建议注定会失败。

上面的“天真而缓慢的实现”会导致足够多的错误,以至于一些FTP服务器会切断您的连接(这可能是大约7个FTP服务器之后发生的情况……)。

相关问题 更多 >

    热门问题