Python kullanarak bir klasördeki en son dosya nasıl elde edilir


127

Python kullanarak bir klasörün en son dosyasını almam gerekiyor. Kodu kullanırken:

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

Aşağıdaki hatayı alıyorum:

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


2
Hangi dosyayı bulmaya çalışıyorsun? ilgili kodunuzu soruna ekleyin.
Naeem Ul Wahhab

1
Neden sizin için çalışmayabileceğini tahmin ediyorum: "dosyalar" bir dosya adı öğeleri listesi mi yoksa tek bir dosya adı dizesi mi?
mpurg

Yanıtlar:


324

filesDeğişkene atanan şey yanlıştır. Aşağıdaki kodu kullanın.

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
Bir dosya yerine en son oluşturulan / değiştirilen klasörü bulmak istersem ne olur?
Bağlantı

1
@Link aynı kod bunun için çalışıyor. Bir klasörü kontrol etmek istiyorsanız ya da kontrol edemiyorsanızif os.path.isdir(latest_file):
Marlon Abeykoon

6
Tuhaf. En son dosyayı almak için "min" kullanmak zorunda kaldım. Etrafta arama yapan bazıları bunun os'a özgü olduğunu ima etti.
Graeck

15
Bu mükemmel bir cevap - TEŞEKKÜRLER! pathlib.PathNesnelerle çalışmayı dizeler ve os.path'den daha çok seviyorum. Pathlib.Path nesneleri ile cevabınız şöyle olur: list_of_paths = folder_path.glob('*'); latest_path = max(list_of_paths, key=lambda p: p.stat().st_ctime)
Phil

4
@phil Nesnelerde os.path.getctimebile anahtar olarak kullanabilirsiniz Path.
Berislav Lopac

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

oldukça eksik koddur. Nedir files? Muhtemelen içinden çıkan dosya adlarının bir listesidir os.listdir().

Ancak bu liste yalnızca dosya adı parçalarını ("taban adları" olarak da bilinir) listeler, çünkü bunların yolu ortaktır. Doğru kullanmak için ona giden yolla birleştirmeniz (ve onu elde etmek için kullanmanız) gerekir.

Örneğin (test edilmemiş):

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

Olumsuz oy kullananların tam olarak neyin yanlış olduğunu açıklayabileceğinden eminim.
glglgl

3
Dunno, senin için test edildi, işe yarıyor gibi görünüyor. Üstelik, biraz açıklamayı önemseyen tek kişi sendin. Kabul edilen cevabı okumak bana 'glob' şeyine ihtiyaç olduğunu düşündürdü, oysa kesinlikle gerekli değil. Teşekkürler
Arnaud P

4
@David Elbette. Sadece if basename.endswith('.csv')listeyi anlama bölümüne ekleyin .
glglgl

1
@BreakBadSP Esneklik istiyorsanız, haklısınız. Belirli bir dizinle sınırlıysanız, sizinki nasıl daha verimli olabilir anlamıyorum. Ancak bazen okunabilirlik verimlilikten daha önemlidir, bu nedenle sizinki bu anlamda gerçekten daha iyi olabilir.
glglgl

1
Bunun için teşekkürler, bunu birçok ETL işlevimde kullandım!
Manakin

9

Daha verimli olduğu için glob.iglob()yerine kullanmanızı öneririm glob.glob().

glob.iglob () glob () ile aynı değerleri gerçekten aynı anda depolamadan veren bir yineleyici döndürür.

Bu glob.iglob()da daha verimli olacak demektir .

Kalıbımla eşleşen en son dosyayı bulmak için çoğunlukla aşağıdaki kodu kullanıyorum:

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


NOT: maxFonksiyonun çeşitleri vardır, en son dosyayı bulmamız durumunda aşağıdaki varyantı kullanacağız: max(iterable, *[, key, default])

yinelenebilir olması gerekir, böylece ilk parametreniz yinelenebilir olmalıdır. Maksimum sayı bulma durumunda, sığır varyantını kullanabiliriz:max (num1, num2, num3, *args[, key])


1
Bu max()türden hoşlanıyorum . Benim durumumda, key=os.path.basenamedosya adlarında zaman damgaları olduğu için farklı bir kullandım .
MarkHu

4

Öğeleri oluşturma zamanına göre sıralamayı deneyin. Aşağıdaki örnek, bir klasördeki dosyaları sıralar ve en son olan ilk öğeyi alır.

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

Yorum yapacak itibarım yok ama Marlon Abeykoons'un cevabından gelen ctime benim için doğru sonucu vermedi. Mtime kullanmak hile yapar. (anahtar = os.path.get m zamanı))

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

Bu problem için iki cevap buldum:

python os.path.getctime max en son döndürmez Unix sisteminde python - getmtime () ve getctime () arasındaki fark


1

(Yanıtı iyileştirmek için düzenlendi)

Önce get_latest_file işlevini tanımlayın

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

Ayrıca bir docstring de kullanabilirsiniz!

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 kullanıyorsanız iglob'u kullanabilirsiniz yerine .

En son dosyanın adını döndürmek için kodu tamamlayın:

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

Parçayı nereden aldın JuniperAccessLog-standalone-FCL_VPN?
glglgl

Bu, Windows 10 altında 0 uzunluktaki dosyalarda başarısız oluyor.
Superdooperhero

1

Yukarıdaki önerileri kullanmaya çalıştım ve programım çöktü, tanımlamaya çalıştığım dosyanın kullanıldığını anladım ve 'os.path.getctime' kullanmaya çalışırken çöktü. sonunda benim için işe yarayan şuydu:

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

bu kodlar, iki dosya listesi arasındaki nadir nesneyi alır, en zarif değildir ve aynı anda birden fazla dosya oluşturulursa, muhtemelen kararlı olmayacaktır.


1

Windows (0.05s) üzerinde çok daha hızlı bir yöntem, bunu yapan bir bat betiği çağırın:

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\questionaraştırmak istediğiniz dizin nerede .

get_latest.py

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

bir dosya bulursa stdout, yol vestderr Yoktur.

stdout.decode("utf-8").rstrip()Dosya adının kullanılabilir dize temsilini elde etmek için kullanın .


Bunun neden aşağı oylar aldığından emin değilim, bu görevi hızlı bir şekilde yapması gerekenler için bulabildiğim en hızlı yöntem bu. Ve bazen bunu çok hızlı yapmak gerekir.
ic_fl2

Olumlu oy alın. Bunu Windows'ta yapmıyorum, ancak hız arıyorsanız, diğer yanıtlar bir dizindeki tüm dosyaların yinelemesini gerektirir. Dolayısıyla, işletim sisteminizde listelenen dosyaların bir sıralama düzenini belirten kabuk komutları mevcutsa, bunun ilk veya son sonucunu çekmek daha hızlı olmalıdır .
Jim Hunziker

1
Teşekkürler Aslında bundan daha iyi bir çözümle daha çok ilgileniyorum (benzer şekilde hızlı ama saf python'da olduğu gibi), bu yüzden birinin bunu detaylandırmasını umuyordum.
ic_fl2

2
Üzgünüm ama eksi oy vermek zorunda kaldım ve nedenlerini açıklamak için size nezaket göstereceğim. Bunun en büyük nedeni, Windows altında çalıştırılmadığı sürece python (çapraz platform değil) kullanmamasıdır. İkincisi, bu "daha hızlı bir yöntem" değildir (daha hızlı olan, belgeleri okumayı rahatsız etmeyen, hızlı ve kirli anlamına gelmedikçe) - başka bir betiğe ateş etmek herkesin bildiği gibi yavaştır.
MarkHu

1
@MarkHu Aslında bu betik, büyük bir klasörün içeriğini bir python betiğinden hızlı bir şekilde kontrol etme gerekliliğinden doğdu. Bu durumda, daha hızlı yöntem, en yeni klasörün dosya adını en hızlı (veya saf bir python yönteminden daha hızlı) almak anlamına gelir. Linux için benzer bir komut dosyası eklemekten çekinmeyin ls -Art | tail -n 1. Lütfen iddialarda bulunmadan önce bir çözümün performansını değerlendirin.
ic_fl2

0

Bunu Python 3'te dosya adında kalıp eşleştirme dahil kullanıyorum.

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)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.