So erhalten Sie mit Python die neueste Datei in einem Ordner

126

Ich muss die neueste Datei eines Ordners mit Python abrufen. Während Sie den Code verwenden:

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

Ich erhalte die folgende Fehlermeldung:

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

garlapak
quelle
2
Welche Datei versuchen Sie zu finden? Fügen Sie der Frage Ihren relevanten Code hinzu.
Naeem Ul Wahhab
1
Ich vermute, warum es bei Ihnen möglicherweise nicht funktioniert: Ist "files" eine Liste von Dateinamenelementen oder eine einzelne Dateinamenzeichenfolge?
mpurg

Antworten:

321

Was auch immer der filesVariablen zugewiesen ist, ist falsch. Verwenden Sie den folgenden Code.

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
Marlon Abeykoon
quelle
4
Was ist, wenn ich anstelle einer Datei den zuletzt erstellten / geänderten Ordner suchen möchte?
Link
1
@Link der gleiche Code funktioniert dafür. Wenn Sie überprüfen möchten, ob es sich um einen Ordner handelt oder nicht, können Sie dies überprüfenif os.path.isdir(latest_file):
Marlon Abeykoon,
6
Seltsam. Ich musste "min" verwenden, um die neueste Datei zu erhalten. Einige Suchanfragen deuteten darauf hin, dass es spezifisch ist.
Graeck
15
Dies ist eine ausgezeichnete Antwort - DANKE! Ich arbeite pathlib.Pathlieber mit Objekten als mit Strings und os.path. Mit pathlib.Path-Objekten lautet Ihre Antwort: list_of_paths = folder_path.glob('*'); latest_path = max(list_of_paths, key=lambda p: p.stat().st_ctime)
Phil
4
@phil Sie können os.path.getctimeauch mit PathObjekten als Schlüssel verwenden .
Berislav Lopac
42
max(files, key = os.path.getctime)

ist ziemlich unvollständiger Code. Was ist files? Es ist wahrscheinlich eine Liste von Dateinamen, die aus os.listdir().

Diese Liste listet jedoch nur die Dateinamen-Teile (auch als "Basisnamen" bezeichnet) auf, da deren Pfad häufig vorkommt. Um es richtig zu verwenden, müssen Sie es mit dem Pfad kombinieren, der dorthin führt (und verwendet wird, um es zu erhalten).

Wie (ungetestet):

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
quelle
Ich bin sicher, die Downvoter können erklären, was genau falsch ist.
glglgl
3
Keine Ahnung, für Sie getestet, es scheint zu funktionieren. Darüber hinaus waren Sie der einzige, dem es wichtig war, ein wenig zu erklären. Das Lesen der akzeptierten Antwort ließ mich denken, dass 'glob' Ding gebraucht wurde, während es absolut nicht ist. Vielen Dank
Arnaud P
4
@ David Natürlich. Einfach if basename.endswith('.csv')in das Listenverständnis einfügen .
glglgl
1
@BreakBadSP Wenn Sie Flexibilität wünschen, haben Sie Recht. Wenn Sie auf ein bestimmtes Verzeichnis beschränkt sind, sehe ich nicht, wie Ihr Verzeichnis möglicherweise effizienter sein kann. Aber manchmal ist Lesbarkeit wichtiger als Effizienz, daher ist Ihre Lesbarkeit in diesem Sinne möglicherweise besser.
glglgl
1
Vielen Dank dafür, ich habe dies in so vielen meiner ETL-Funktionen verwendet!
Manakin
9

Ich würde vorschlagen, glob.iglob()anstelle von zu verwenden glob.glob(), da es effizienter ist.

glob.iglob () Gibt einen Iterator zurück, der dieselben Werte wie glob () liefert, ohne alle gleichzeitig zu speichern.

Welches Mittel glob.iglob()wird effizienter sein.

Ich verwende meistens den folgenden Code, um die neueste Datei zu finden, die meinem Muster entspricht:

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


HINWEIS: Es gibt maxFunktionsvarianten. Wenn Sie die neueste Datei finden, verwenden wir die folgende Variante: max(iterable, *[, key, default])

Dies muss iterierbar sein, sodass Ihr erster Parameter iterierbar sein sollte. Wenn wir maximal viele Zahlen finden, können wir die folgende Variante verwenden:max (num1, num2, num3, *args[, key])

BreakBadSP
quelle
1
Ich mag diese max()Art. In meinem Fall habe ich einen anderen verwendet, key=os.path.basenameda die Dateinamen Zeitstempel enthielten.
MarkHu
4

Versuchen Sie, Elemente nach Erstellungszeit zu sortieren. Das folgende Beispiel sortiert Dateien in einem Ordner und erhält das erste Element, das aktuell ist.

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]
türkus
quelle
4

Mir fehlt der Ruf, einen Kommentar abzugeben, aber die Zeit von Marlon Abeykoons Antwort ergab nicht das richtige Ergebnis für mich. Die Verwendung von mtime reicht jedoch aus. (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

Ich habe zwei Antworten für dieses Problem gefunden:

python os.path.getctime max gibt nicht den neuesten Unterschied zwischen python - getmtime () und getctime () im Unix-System zurück

crlf
quelle
1

(Bearbeitet, um die Antwort zu verbessern)

Definieren Sie zuerst eine Funktion get_latest_file

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

Sie können auch einen Docstring verwenden!

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)

Wenn Sie Python 3 verwenden , können Sie stattdessen iglob verwenden.

Vollständiger Code, um den Namen der neuesten Datei zurückzugeben:

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
Naeem Ul Wahhab
quelle
Woher hast du das JuniperAccessLog-standalone-FCL_VPNTeil?
glglgl
Dies schlägt bei Dateien mit einer Länge von 0 unter Windows 10
fehl
1

Ich habe versucht, die oben genannten Vorschläge zu verwenden, und mein Programm ist abgestürzt, als ich herausgefunden habe, dass die Datei, die ich identifizieren möchte, verwendet wurde, und als ich versuchte, 'os.path.getctime' zu verwenden, ist sie abgestürzt. Was schließlich für mich funktioniert hat war:

    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,'*'))))

Dieser Code erhält das ungewöhnliche Objekt zwischen den beiden Dateilisten. Es ist nicht das eleganteste. Wenn mehrere Dateien gleichzeitig erstellt werden, ist es wahrscheinlich nicht stabil

AlexFink
quelle
1

Eine viel schnellere Methode unter Windows (0.05s), rufen Sie ein Bat-Skript auf, das dies tut:

get_latest.bat

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

Wo \\directory\in\questionist das Verzeichnis, das Sie untersuchen möchten?

get_latest.py

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

Wenn es eine Datei findet, stdoutist der Pfad undstderr Keine.

Verwenden Sie stdout.decode("utf-8").rstrip()diese Option , um die verwendbare Zeichenfolgendarstellung des Dateinamens abzurufen.

ic_fl2
quelle
Ich bin mir nicht sicher, warum dies zu Abstimmungen führt. Für diejenigen, die diese Aufgabe schnell erledigen müssen, ist dies die schnellste Methode, die ich finden konnte. Und manchmal ist es notwendig, dies sehr schnell zu tun.
ic_fl2
Habe eine Gegenstimme. Ich mache das nicht in Windows, aber wenn Sie nach Geschwindigkeit suchen, erfordern die anderen Antworten eine Iteration aller Dateien in einem Verzeichnis. Wenn also Shell-Befehle in Ihrem Betriebssystem verfügbar sind, die eine Sortierreihenfolge der aufgelisteten Dateien angeben, sollte das erste oder letzte Ergebnis schneller abgerufen werden.
Jim Hunziker
1
Vielen Dank, ich bin eigentlich mehr besorgt über eine bessere Lösung als diese (wie in ähnlich schnellem, aber reinem Python), also hoffte ich, dass jemand darauf näher eingehen könnte.
ic_fl2
2
Entschuldigung, aber ich musste abstimmen, und ich gebe Ihnen die Höflichkeit, Gründe dafür zu erklären. Der Hauptgrund ist, dass es kein Python (nicht plattformübergreifend) verwendet und somit nicht funktioniert, es sei denn, es wird unter Windows ausgeführt. Zweitens ist dies keine "schnellere Methode" (es sei denn, schneller bedeutet schnell und schmutzig, sich nicht die Mühe zu machen, Dokumente zu lesen) - das Weitergeben an ein anderes Skript ist notorisch langsam.
MarkHu
1
@MarkHu Eigentlich entstand dieses Skript aus der Notwendigkeit heraus, den Inhalt eines großen Ordners schnell anhand eines Python-Skripts zu überprüfen. In diesem Fall bedeutet eine schnellere Methode, dass der Dateiname des neuesten Ordners am schnellsten abgerufen wird (oder schneller als bei einer reinen Python-Methode). Fühlen Sie sich frei, ein ähnliches Skript für Linux hinzuzufügen, wahrscheinlich basierend auf ls -Art | tail -n 1. Bitte bewerten Sie die Leistung einer Lösung, bevor Sie Ansprüche geltend machen.
ic_fl2
0

Ich habe dies in Python 3 verwendet, einschließlich Mustervergleich für den Dateinamen.

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)
Jamie Bull
quelle