Pythonを使用してフォルダー内の最新ファイルを取得する方法


126

pythonを使用してフォルダーの最新ファイルを取得する必要があります。コードを使用している間:

max(files, key = os.path.getctime)

以下のエラーが発生します:

FileNotFoundError: [WinError 2] The system cannot find the file specified: 'a'


2
どのファイルを探しますか?質問に関連するコードを追加します。
Naeem Ul Wahhab 2016

1
「files」はファイル名要素のリストですか、それとも単一のファイル名文字列ですか?
mpurg 2016

回答:


321

files変数に割り当てられているものはすべて正しくありません。次のコードを使用します。

import glob
import os

list_of_files = glob.glob('/path/to/folder/*') # * means all if need specific format then *.csv
latest_file = max(list_of_files, key=os.path.getctime)
print latest_file

4
ファイルの代わりに、作成/変更された最新のフォルダーを検索するにはどうすればよいですか?
リンク

1
@Link同じコードがそのために機能します。あなたがそれをチェックしたいなら、あなたはチェックできませんif os.path.isdir(latest_file):
Marlon Abeykoon

6
変だ。最新のファイルを取得するには、「min」を使用する必要がありました。周りを検索している人は、OS固有であることをほのめかしています。
Graeck

15
これはすばらしい回答です。ありがとうございます。私は仕事に好きなpathlib.Path文字列とはos.pathよりもオブジェクトより。:pathlib.Pathは、あなたの答えになるオブジェクトを持つ list_of_paths = folder_path.glob('*'); latest_path = max(list_of_paths, key=lambda p: p.stat().st_ctime)
フィル・

4
@phil オブジェクトos.path.getctimeでも、キーとして使用できPathます。
Berislav Lopac

42
max(files, key = os.path.getctime)

かなり不完全なコードです。なにfiles?おそらく、から出てくるファイル名のリストですos.listdir()

ただし、パスが共通であるため、このリストにはファイル名の部分(別名「ベース名」)のみがリストされています。それを正しく使用するためには、それをそれへの(そしてそれを取得するために使用される)パスと組み合わせる必要があります。

(テストされていない)など:

def newest(path):
    files = os.listdir(path)
    paths = [os.path.join(path, basename) for basename in files]
    return max(paths, key=os.path.getctime)

反対投票者が正確に何が悪いのか説明できると私は確信しています
glglgl 2016

3
Dunno、あなたのためにテストされました、それはうまくいくようです。その上、あなたが少し説明を気にかけたのはあなただけだった。受け入れられた答えを読んで、私は「グロブ」のものが必要であると思いましたが、それは絶対に必要ではありません。ありがとう
Arnaud P

4
@Davidもちろんです。if basename.endswith('.csv')リスト内包表記に挿入するだけです。
glglgl 2018

1
@BreakBadSP柔軟性が必要な場合は、そのとおりです。あなたが特定のディレクトリに制限されている場合、私はあなたがおそらくもっと効率的になることができるかわかりません。ただし、効率よりも可読性の方が重要な場合があるため、その意味で実際に優れている場合があります。
glglgl 2018年

1
このおかげで、私はこれを私のETL関数の多くで使用しました!
Manakin

9

より効率的glob.iglob()であるためglob.glob()、の代わりに使用することをお勧めします。

glob.iglob()実際にすべてを同時に格納せずにglob()と同じ値を生成する反復子を返します。

つまり glob.iglob()、より効率的になります。

私は主に以下のコードを使用して、パターンに一致する最新のファイルを見つけます:

LatestFile = max(glob.iglob(fileNamePattern),key=os.path.getctime)


注:のバリアントがあります max関数のます。最新のファイルを見つける場合は、以下のバリアントを使用します。 max(iterable, *[, key, default])

これは反復可能である必要があるため、最初のパラメーターは反復可能でなければなりません。numの最大値を見つける場合、beowバリアントを使用できます。max (num1, num2, num3, *args[, key])


1
私はこのmax()種が好きです。私の場合、key=os.path.basenameファイル名にタイムスタンプが含まれているため、別のものを使用しました。
MarkHu

4

作成時間でアイテムを並べ替えてみてください。以下の例では、フォルダー内のファイルを並べ替え、最新の最初の要素を取得します。

import glob
import os

files_path = os.path.join(folder, '*')
files = sorted(
    glob.iglob(files_path), key=os.path.getctime, reverse=True) 
print files[0]

4

私はコメントする評判がありませんが、Marlon Abeykoons応答からのctimeは正しい結果を与えませんでした。ただし、mtimeを使用するとうまくいきます。(key = os.path.get m time))

import glob
import os

list_of_files = glob.glob('/path/to/folder/*') # * means all if need specific format then *.csv
latest_file = max(list_of_files, key=os.path.getmtime)
print latest_file

その問題について2つの答えが見つかりました。

python os.path.getctime maxがpythonの最新の 違いを返さない-UNIXシステムでのgetmtime()とgetctime()


1

(回答を改善するために編集)

最初に関数get_latest_fileを定義します

def get_latest_file(path, *paths):
    fullpath = os.path.join(path, paths)
    ...
get_latest_file('example', 'files','randomtext011.*.txt')

docstringを使用することもできます!

def get_latest_file(path, *paths):
    """Returns the name of the latest (most recent) file 
    of the joined path(s)"""
    fullpath = os.path.join(path, *paths)

Python 3を使用している場合はiglobを使用できます代わりに。

最新のファイルの名前を返す完全なコード:

def get_latest_file(path, *paths):
    """Returns the name of the latest (most recent) file 
    of the joined path(s)"""
    fullpath = os.path.join(path, *paths)
    files = glob.glob(fullpath)  # You may use iglob in Python3
    if not files:                # I prefer using the negation
        return None                      # because it behaves like a shortcut
    latest_file = max(files, key=os.path.getctime)
    _, filename = os.path.split(latest_file)
    return filename

どこJuniperAccessLog-standalone-FCL_VPNから手に入れたのですか?
glglgl 2016

これは、Windows 10の下に長さ0のファイルに失敗した
Superdooperhero

1

上記の提案を使用しようとしたところ、プログラムがクラッシュしました。特定しようとしているファイルが使用されていることがわかり、 'os.path.getctime'を使用しようとするとクラッシュしました。最終的に私のために働いたのは:

    files_before = glob.glob(os.path.join(my_path,'*'))
    **code where new file is created**
    new_file = set(files_before).symmetric_difference(set(glob.glob(os.path.join(my_path,'*'))))

このコードは、2つのファイルリストのセットの間で一般的でないオブジェクトを取得します。これは、最もエレガントではありません。同時に複数のファイルが作成された場合、おそらく安定しません。


1

Windowsでのはるかに高速なメソッド(0.05秒)は、これを行うbatスクリプトを呼び出します。

get_latest.bat

@echo off
for /f %%i in ('dir \\directory\in\question /b/a-d/od/t:c') do set LAST=%%i
%LAST%

どこ \\directory\in\questionあなたが調査したいディレクトリです。

get_latest.py

from subprocess import Popen, PIPE
p = Popen("get_latest.bat", shell=True, stdout=PIPE,)
stdout, stderr = p.communicate()
print(stdout, stderr)

ファイルstdoutが見つかった場合はパスであり、stderrあり、Noneです。

使用するstdout.decode("utf-8").rstrip()ファイル名の使用可能な文字列表現を取得します。


なぜこれが投票を引き付けるのかわかりません。このタスクをすばやく実行する必要がある人にとって、これは私が見つけた最も速い方法です。そして時にはこれを非常に迅速に行う必要がある。
ic_fl2

賛成票を持っています。私はWindowsでこれを行っていませんが、速度を求めている場合、他の答えはディレクトリ内のすべてのファイルの反復を必要とします。表示されているファイルのソート順を指定して、あなたのOSで、シェルのコマンドが用意されていた場合ので、それの最初または最後の結果を引っ張るとすべき速くなります。
ジムHunziker

1
おかげで私は実際にはこれよりも優れたソリューションに関心があります(同様に高速ですが純粋なpythonの場合と同様)。誰かがそれについて詳しく説明できることを望んでいました。
ic_fl2

2
申し訳ありませんが、私は反対票を投じなければなりませんでした。理由を説明するために礼儀をお伝えします。最大の理由は、Windowsで実行しない限り、Python(クロスプラットフォームではない)を使用していないため、壊れていることです。第二に、これは「より速い方法」ではありません(より速いということは、文書を読み飛ばすことを意味する場合を除いて)。
MarkHu

1
@MarkHu実際、このスクリプトは、大きなスクリプトの内容をPythonスクリプトからすばやく確認する必要性から生まれました。したがって、この場合、より高速なメソッドは、最新のフォルダのファイル名を最も速く取得します(または、純粋なpythonメソッドよりも高速です)。おそらくに基づいて、Linux用の同様のスクリプトを自由に追加してくださいls -Art | tail -n 1。ソリューションについて主張する前に、ソリューションのパフォーマンスを評価してください。
ic_fl2

0

これをPython 3で使用しており、ファイル名のパターンマッチングも含まれています。

from pathlib import Path

def latest_file(path: Path, pattern: str = "*"):
    files = path.glob(pattern)
    return max(files, key=lambda x: x.stat().st_ctime)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.