6

FTPサーバーからすべてのディレクトリの名前を取得し、それらを階層順に多次元リストまたはdictに保存しようとしています。

したがって、たとえば、次の構造を含むサーバー:

/www/
    mysite.com
        images
            png
            jpg

スクリプトの最後に、次のようなリストが表示されます

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

私は次のような再帰関数を使用してみました:def traverse(dir):FTP.dir(dir、traverse)

FTP.dirは、次の形式で行を返します。

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

したがって、line [56:]を実行すると、ディレクトリ名(mysite.com)だけが表示されます。これを再帰関数で使用します。

しかし、私はそれを機能させることができません。私は多くの異なるアプローチを試しましたが、それを機能させることができません。FTPエラーもたくさんあります(ディレクトリが見つからない-これは論理的な問題であり、サーバーから予期しないエラーが返されることがあり、ログが残らず、デバッグできません)

一番下の質問: FTPサーバーから階層ディレクトリリストを取得するにはどうすればよいですか?

4

5 に答える 5

10

これは素朴で遅い実装です。各ディレクトリエントリに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()
于 2009-12-06T09:59:56.763 に答える
4

これが私のために働いたPython3スクリプトの最初のドラフトです。を呼び出すよりもはるかに高速です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])
于 2016-02-18T00:34:17.687 に答える
2

これは気に入らないでしょうが、「サーバーに依存します」、より正確には「サーバーの出力形式に依存します」。

異なるサーバーを設定して異なる出力を表示できるため、一般的なケースでは、最初の提案は失敗に終わります。

上記の「素朴で遅い実装」は、いくつかのFTPサーバーがあなたを遮断するのに十分なエラーを引き起こします(これはおそらくそれらの約7つの後に起こったことです...)。

于 2009-12-06T22:01:36.023 に答える
2

サーバーがコマンドをサポートしている場合は、その回答MLSDの「ディレクトリとその子孫」コードを使用します。

于 2010-06-24T23:12:06.050 に答える
-3

Pythonを使用している場合は、以下を参照してください。

http://docs.python.org/library/os.path.html(os.path.walk

これに適したモジュールがすでにある場合は、車輪の再発明を行わないでください。とにかく、上記の2つのスポットが2つのアップを獲得したとは信じられません。

于 2009-12-06T22:14:13.203 に答える