Як отримати останній файл у папці за допомогою python


126

Мені потрібно отримати останній файл папки за допомогою python. Під час використання коду:

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

Я отримую помилку нижче:

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


2
Який файл ви намагаєтесь знайти? додати відповідний код до анкети.
Naeem Ul Wahhab

1
Я здогадуюсь, чому це може не працювати для вас: "файли" - це список елементів імені файлу чи одна рядок імені файлу?
mpurg

Відповіді:


322

Що б не було присвоєно 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):
Марлон Абейкон

6
Дивно. Мені довелося скористатися "min", щоб отримати останній файл. Деякі пошуки навколо натякали, що це специфічно.
Грейк

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об’єктами.
Берислав Лопак

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

3
Данно, перевірений на вас, це, здається, працює. На додаток до цього, ти був єдиним, хто піклувався про те, щоб трохи пояснити. Читання прийнятої відповіді змусило мене думати, що потрібна річ «глобус», тоді як це абсолютно не так. Спасибі
Арно П

4
@David Звичайно. Просто вставте if basename.endswith('.csv')в список розуміння.
glglgl

1
@BreakBadSP Якщо ви хочете гнучкості, ви маєте рацію. Якщо ви обмежені певним каталогом, я не бачу, як ваша може бути ефективнішою. Але іноді читабельність важливіша за ефективність, тому ваша справді може бути кращою в цьому сенсі.
glglgl

1
Дякую за це, я використав це у багатьох своїх функціях ETL!
Манакін

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: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

Мені не вистачає репутації для коментування, але час з відповіді Марлона Абейконса не дав мені правильного результату. Використання mtime, однак, і трюк. (ключ = os.path.get м час))

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 () в unix-системі


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, який робить це:

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, але якщо ви шукаєте швидкості, для інших відповідей потрібна ітерація всіх файлів у каталозі. Тож якщо доступні команди оболонки у вашій ОС, які задають порядок сортування перелічених файлів, витягнути перший або останній результат цього повинен бути швидше.
Джим Ханзікер

1
Дякую, я насправді більше переймаюся кращим рішенням, ніж це (як у подібному швидкому, але чистому пітоні), тому сподівався, що хтось зможе детальніше розглянути це.
ic_fl2

2
Вибачте, але мені довелося подати заяву, і я надаю вам ввічливість пояснити причини. Найбільшою причиною є те, що він не використовує python (не крос-платформу), таким чином, зламаний, якщо не працює під Windows. По-друге, це не "швидший метод" (якщо швидше не означає швидке і брудне-не набридлене для читання документів) - передача іншого сценарію, як відомо, повільно.
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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.