ファイルのリストを解析してPythonでファイル名だけを取得するにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/237699

質問

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

役に立ちましたか?

解決

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

他のヒント

このベストアンサー

ftp.retrlines()の代わりに ftp.nlst()を使用することもできます。まさにあなたが望むものが得られます。

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

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

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

E.G:

# 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)

and

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

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

また、何らかの理由でretrlines()を使用してスタックしている場合、少し最適性の低いメソッドは、関数を2番目の引数としてretrlines()に渡すことです。リスト内の各アイテムに対して呼び出されます。したがって、次のようなもの(「ftp」という名前のFTPオブジェクトがある場合)も同様に機能します。

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

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

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

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

  

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:])

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

FTPDirectory クラスのインスタンス( ftpd など)を使用し、接続された ftplib.FTP <で .getdata メソッドを呼び出します/ code>インスタンスを正しいフォルダーに配置すると、次のことができます:

directory_filenames= [ftpfile.name for ftpfile in ftpd.files]

それはあなたのために働くはずだと思います。

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つのスペースに置き換える。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top