5

では、Python のftplibを使用して FTP サーバーからログ ファイルのリストを取得するとします。そのファイルのリストを解析して、リスト内のファイル名 (最後の列) だけを取得するにはどうすればよいですか? 出力例については、上記のリンクを参照してください。

4

7 に答える 7

9

retrlines()を使用することは、コンソールに出力するだけであり、その出力を取得するためにトリッキーなことをしなければならないため、おそらく最良のアイデアではありません。おそらくより良い方法は、nlst()メソッドを使用することです。これは、必要なもの、つまりファイル名のリストを正確に返します。

于 2008-10-26T07:55:46.700 に答える
8

このベストアンサー

ftp.nlst()の代わりに使用することをお勧めしますftp.retrlines()。それはあなたが望むものを正確に与えるでしょう。

できない場合は、以下をお読みください。

sysadminプロセスのジェネレーター

彼の今では有名なレビュー、システムプログラマーのためのジェネレータートリックの紹介で、David M. Beazleyは、wuickと再利用可能なコードでこの種のデータ問題に答えるために多くのレシピを提供しています。

EG:

# empty list that will receive all the log entry
log = [] 
# we pass a callback function bypass the print_line that would be called by retrlines
# we do that only because we cannot use something better than retrlines
ftp.retrlines('LIST', callback=log.append)
# we use rsplit because it more efficient in our case if we have a big file
files = (line.rsplit(None, 1)[1] for line in log)
# get you file list
files_list = list(files)

すぐにリストを生成してみませんか?

これを行うと、柔軟性が大幅に向上するためです。ファイルを変換する前に、任意の中間ジェネレーターをフィルターに適用できます。files_listパイプのように、ラインを追加し、過熱することなくプロセスを追加します(ジェネレーターであるため)。そして、あなたが取り除けばretrlines、それでもうまくいきます。リストを一度も保存しないので、それはさらに良いことです。

編集:まあ、私は他の答えへのコメントを読みました、そしてそれは名前にスペースがあるならばこれはうまくいかないと言います。

かっこいい、これはこの方法が便利な理由を説明します。プロセスで何かを変更したい場合は、行を変更するだけです。スワップ:

files = (line.rsplit(None, 1)[1] for line in log)

# join split the line, get all the item from the field 8 then join them
files = (' '.join(line.split()[8:]) for line in log)

わかりました、これはここでは明らかではないかもしれませんが、巨大なバッチプロセススクリプトの場合、それは素晴らしいです:-)

于 2008-10-26T09:09:11.963 に答える
1

ちなみに、なんらかの理由でretrlines()を使用している場合は、retrlines()の2番目の引数として関数を渡すのが少し最適ではありません。リスト内のアイテムごとに呼び出されます。したがって、次のようなもの(「ftp」という名前のFTPオブジェクトがあると仮定)も同様に機能します。

filenames = []
ftp.retrlines('LIST', lambda line: filenames.append(line.split()[-1]))

リスト'filenames'は、ファイル名のリストになります。

于 2008-10-26T07:59:52.260 に答える
1

出力のすべてのファイル名は同じ列から始まるため、最初の行のドットの位置を取得するだけです。

drwxrwsr-x 5 ftp-usr pdmaint 1536 Mar 20 09:48 .

次に、そのドットの位置を開始インデックスとして使用して、ファイル名を他の行からスライスします。

ドットは行の最後の文字であるため、行の長さから1を引いたものをインデックスとして使用できます。したがって、最終的なコードは次のようになります。

lines = ftp.retrlines('LIST')
lines = lines.split("\n") # This should split the string into an array of lines

filename_index = len(lines[0]) - 1
files = []

for line in lines:
    files.append(line[filename_index:])
于 2008-10-26T08:00:33.320 に答える
1

ftplib.FTP.nlst()が機能しない理由はありますか?チェックしたところ、指定されたディレクトリ内のファイルの名前のみが返されます。

于 2008-10-26T08:15:24.273 に答える
1

FTP サーバーがコマンドをサポートしている場合は、その回答MLSDのセクション「単一ディレクトリのケース」を参照してください。

クラスのインスタンス (たとえばftpd) を使用し、接続されたインスタンスでそのメソッドを正しいフォルダーにFTPDirectory呼び出すと、次のことができます。.getdataftplib.FTP

directory_filenames= [ftpfile.name for ftpfile in ftpd.files]
于 2010-06-24T23:17:14.247 に答える
0

私はそれがあなたのために働くはずだと信じています。

file_name_list = [' '.join(each_file.split()).split()[-1] for each_file_detail in file_list_from_log]

ノート -

  1. ここでは、コンソールではなく、プログラム(リストとして)にデータが必要であると想定しています。

  2. each_file_detailは、プログラムによって生成されている各行です。

  3. '' .join(each_file.split())

複数のスペースを1つのスペースに置き換えます。

于 2008-10-26T07:52:53.787 に答える