ファイルのリストを解析してPythonでファイル名だけを取得するにはどうすればよいですか?
質問
では、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]
注-
-
ここでは、コンソールではなく、プログラム内のデータが(リストとして)必要であると仮定しています。
-
each_file_detailは、プログラムによって生成されている各行です。
-
'' .join(each_file.split())
複数のスペースを1つのスペースに置き換える。