วิธีรับไฟล์ล่าสุดในโฟลเดอร์โดยใช้ python


128

ฉันต้องการรับไฟล์ล่าสุดของโฟลเดอร์โดยใช้ python ขณะใช้รหัส:

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

ฉันได้รับข้อผิดพลาดด้านล่าง:

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


2
ลองหาไฟล์ไหน เพิ่มรหัสที่เกี่ยวข้องของคุณลงใน quesiton
Naeem Ul Wahhab

1
ฉันเดาว่าทำไมมันถึงใช้ไม่ได้สำหรับคุณ: "ไฟล์" เป็นรายการขององค์ประกอบชื่อไฟล์หรือสตริงชื่อไฟล์เดียวหรือไม่?
mpurg

คำตอบ:


325

สิ่งที่กำหนดให้กับ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
@ ลิงก์รหัสเดียวกันใช้งานได้ หากคุณต้องการตรวจสอบโฟลเดอร์หรือไม่สามารถตรวจสอบได้if os.path.isdir(latest_file):
Marlon Abeykoon

6
แปลก. ฉันต้องใช้ "นาที" เพื่อรับไฟล์ล่าสุด การค้นหาบางคนบอกเป็นนัยว่าเป็นระบบปฏิบัติการเฉพาะ
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().

แต่รายการนี้แสดงเฉพาะส่วนของชื่อไฟล์ (หรือที่เรียกว่า "basenames") เนื่องจากพา ธ เป็นเรื่องปกติ ในการใช้งานอย่างถูกต้องคุณต้องรวมเข้ากับเส้นทางที่นำไปสู่ ​​(และใช้เพื่อให้ได้มา)

เช่น (ยังไม่ทดลอง):

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

3
Dunno ทดสอบสำหรับคุณดูเหมือนว่าจะได้ผล ยิ่งไปกว่านั้นคุณเป็นคนเดียวที่ต้องสนใจที่จะอธิบายสักหน่อย การอ่านคำตอบที่ได้รับการยอมรับทำให้ฉันคิดว่าสิ่งที่ต้องการ 'glob' ในขณะที่มันไม่ใช่อย่างแน่นอน ขอบคุณ
Arnaud P

4
@ เดวิดแน่นอน. เพียงแค่ใส่if basename.endswith('.csv')ลงในความเข้าใจรายการ
glglgl

1
@BreakBadSP ถ้าคุณต้องการความยืดหยุ่นคุณคิดถูก หากคุณถูก จำกัด เฉพาะบางไดเรกทอรีฉันไม่เห็นว่าของคุณจะมีประสิทธิภาพมากกว่านี้ได้อย่างไร แต่บางครั้งความสามารถในการอ่านมีความสำคัญมากกว่าประสิทธิภาพดังนั้นของคุณอาจดีกว่าในแง่นั้น
glglgl

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

ซึ่งจำเป็นต้องทำซ้ำได้ดังนั้นพารามิเตอร์แรกของคุณควรทำซ้ำได้ ในกรณีที่พบจำนวนสูงสุดเราสามารถใช้ beow variant: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

ฉันไม่มีชื่อเสียงในการแสดงความคิดเห็น แต่ ctime จากการตอบกลับของ Marlon Abeykoons ไม่ได้ให้ผลลัพธ์ที่ถูกต้องสำหรับฉัน การใช้ mtime เป็นเคล็ดลับ (คีย์ = os.path.get mเวลา))

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

ฉันพบสองคำตอบสำหรับปัญหานั้น:

python os.path.getctime max ไม่ส่งคืน ความแตกต่างล่าสุดระหว่าง python - 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

สิ่งนี้ล้มเหลวในไฟล์ความยาว 0 ภายใต้ Windows 10
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,'*'))))

รหัสนี้ได้รับวัตถุที่ผิดปกติระหว่างชุดไฟล์สองชุดซึ่งไม่ใช่รายการที่หรูหราที่สุดและหากมีการสร้างไฟล์หลายไฟล์ในเวลาเดียวกันมันอาจจะไม่เสถียร


1

วิธีที่เร็วกว่ามากบน windows (0.05s) เรียก bat script ที่ทำสิ่งนี้:

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ไม่มี

ใช้stdout.decode("utf-8").rstrip()เพื่อรับการแสดงสตริงที่ใช้งานได้ของชื่อไฟล์


ไม่แน่ใจว่าเหตุใดสิ่งนี้จึงดึงดูดคะแนนเสียงสำหรับผู้ที่ต้องทำงานนี้อย่างรวดเร็วนี่เป็นวิธีที่เร็วที่สุดที่ฉันสามารถหาได้ และบางครั้งก็จำเป็นต้องทำอย่างรวดเร็ว
ic_fl2

มีการโหวตเพิ่มขึ้น ฉันไม่ได้ทำสิ่งนี้ใน Windows แต่ถ้าคุณกำลังมองหาความเร็วคำตอบอื่น ๆ ต้องการการทำซ้ำไฟล์ทั้งหมดในไดเร็กทอรี ดังนั้นหากคำสั่งเชลล์ในระบบปฏิบัติการของคุณที่ระบุลำดับการจัดเรียงของไฟล์ในรายการพร้อมใช้งานการดึงผลลัพธ์แรกหรือสุดท้ายของผลลัพธ์นั้นควรเร็วกว่า
Jim Hunziker

1
ขอบคุณจริงๆแล้วฉันกังวลกับวิธีแก้ปัญหาที่ดีกว่านี้ (เช่นเดียวกับงูหลามที่เร็ว แต่บริสุทธิ์) ดังนั้นฉันหวังว่าจะมีคนอธิบายอย่างละเอียด
ic_fl2

2
ขอโทษทีฉันต้องโหวตลงคะแนนและฉันจะให้ความอนุเคราะห์อธิบายเหตุผลว่าทำไม เหตุผลที่ใหญ่ที่สุดคือมันไม่ได้ใช้ python (ไม่ใช่ข้ามแพลตฟอร์ม) ดังนั้นจึงเสียเว้นแต่จะทำงานภายใต้ Windows ประการที่สองนี่ไม่ใช่ "วิธีการที่เร็วกว่า" (เว้นแต่ว่าเร็วกว่านั้นหมายถึงการอ่านเอกสารที่รวดเร็วและสกปรกไม่รบกวนการอ่าน) การลอกออกไปยังสคริปต์อื่นนั้นช้าอย่างฉาวโฉ่
MarkHu

1
@MarkHu จริงๆแล้วสคริปต์นี้เกิดจากความจำเป็นในการตรวจสอบเนื้อหาของโฟลเดอร์ขนาดใหญ่อย่างรวดเร็วจากสคริปต์ python ดังนั้นในกรณีนี้วิธีการที่เร็วกว่าหมายถึงทำให้ชื่อไฟล์ของโฟลเดอร์ใหม่ล่าสุดเร็วที่สุด (หรือเร็วกว่าวิธี python แท้) 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.