Как найти файлы и пропустить каталоги в os.listdir

Я использую os.listdir, и он отлично работает, но я также получаю в списке подкаталоги, а это не то, что мне нужно: мне нужны только файлы.

Какую функцию мне нужно использовать для этого?

Я также посмотрел на os.walk, и, кажется, это то, что я хочу, но я не уверен, как это работает.


person Bartee    schedule 05.03.2014    source источник


Ответы (6)


Вам нужно отфильтровать каталоги; os.listdir() перечисляет все имена по заданному пути. Для этого можно использовать os.path.isdir():

basepath = '/path/to/directory'
for fname in os.listdir(basepath):
    path = os.path.join(basepath, fname)
    if os.path.isdir(path):
        # skip directories
        continue

Обратите внимание, что это только отфильтровывает каталоги после перехода по символическим ссылкам. fname не обязательно является обычным файлом, это также может быть символическая ссылка на файл. Если вам нужно также отфильтровать символические ссылки, вам нужно использовать not os.path.islink().

В современной версии Python (3.5 или новее) еще лучше использовать os.scandir(); это создает DirEntry() экземпляров. В общем случае это быстрее, так как загруженный direntry уже кэширует достаточно информации, чтобы определить, является ли запись каталогом или нет:

basepath = '/path/to/directory'
for entry in os.scandir(basepath):
    if entry.isdir():
        # skip directories
        continue
    # use entry.path to get the full path of this entry, or use
    # entry.name for the base filename

Вы можете использовать entry.is_file(follow_symlinks=False), если нужны только обычные файлы (а не симлинки).

os.walk() делает то же самое под капотом; если вам не нужно рекурсивно перемещаться по подкаталогам, вам не нужно использовать здесь os.walk().

person Martijn Pieters    schedule 05.03.2014
comment
Именно то, что я искал. Больше знаний с примером. Мне нужно выбрать один ответ, но я попробую изучить все три добавленные концепции. - person Bartee; 07.03.2014
comment
Преимущество в том, что это решение не становится рекурсивным, а останавливается на первом уровне, я думаю. - person Timo; 24.11.2020
comment
@Timo: он обрабатывает только один уровень каталогов, да. - person Martijn Pieters; 24.11.2020
comment
Развивая свои строки дальше, как бы вы сортировали по времени: files = filter(os.path.isfile, os.listdir(bilder)) files = [os.path.join(bilder, f) for f in files] files.sort(key=os.path.getmtime), а затем ваш код снова с os.listdir и без if? - person Timo; 24.11.2020
comment
@Timo: тогда я бы не стал использовать здесь os.path.getmtime. Используйте os.scandir() вместо os.listdir() и используйте тот факт, что этот API часто уже кэширует информацию mtime. - person Martijn Pieters; 24.11.2020
comment
@Timo: поэтому, если вы используете os.scandir(), вы можете использовать entries = sorted((e for e in os.scandir(bilder) if e.is_file()), key=lambda e: e.stat().st_mtime), а затем извлечь только пути с помощью files = [e.path for e in entries]. - person Martijn Pieters; 24.11.2020
comment
я получаю 'os.stat_result' object has no attribute 'mtime' - person Timo; 25.11.2020
comment
@ Тимо: исправлено. Атрибут называется st_mtime, извините за это. - person Martijn Pieters; 25.11.2020

Вот симпатичная маленькая строчка в виде понимания списка:

[f for f in os.listdir(your_directory) if os.path.isfile(os.path.join(your_directory, f))]

Это будет return и list имен файлов в пределах указанного your_directory.

person anon582847382    schedule 05.03.2014
comment
Альтернатива: filter(os.path.isfile, os.listdir(your_directory)) - person Valentin Lorentz; 06.03.2014
comment
На самом деле это не работает, так как f — это имя файла, а не полный путь. Вам понадобится os.path.isfile(os.path.join(your_directory, f)) там. - person Martijn Pieters; 07.03.2014
comment
мне это понравилось больше, и я также хотел ограничить его расширением, поэтому смог добавить еще одно условие в конце: `and f.endswith('.txt')` . - person Nikhil VJ; 29.03.2018

import os
directoryOfChoice = "C:\\" # Replace with a directory of choice!!!
filter(os.path.isfile, os.listdir(directoryOfChoice))

PS: os.getcwd() возвращает текущий каталог.

person SixSense    schedule 09.11.2014

Решение с os.walk() будет таким:

for r, d, f in os.walk('path/to/dir'):
    for files in f:
       # This will list all files given in a particular directory
person Christopher Galli    schedule 24.09.2020
comment
Что не очевидно, если вы просто копируете/вставляете это, так это то, что он будет перебирать все каталоги во всех подкаталогах начального каталога. - person tripleee; 24.11.2020

Несмотря на то, что это старый пост, позвольте мне добавить представленную библиотеку pathlib. в 3.4, который обеспечивает стиль ООП для обработки каталогов и файлов для полноты картины. Чтобы получить все файлы в каталоге, вы можете использовать

def get_list_of_files_in_dir(directory: str, file_types: str ='*') -> list:
    return [f for f in Path(directory).glob(file_types) if f.is_file()]

Следуя вашему примеру, вы можете использовать его следующим образом:

mypath = '/path/to/directory'
files = get_list_of_files_in_dir(mypath)

Если вам нужно только подмножество файлов в зависимости от расширения файла (например, только файлы csv), вы можете использовать:

files = get_list_of_files_in_dir(mypath, '*.csv')
person dheinz    schedule 22.06.2020

Примечание Атрибуты объекта PEP 471 DirEntry: is_dir(*, follow_symlinks=True)

so...

from os import scandir
folder = '/home/myfolder/'
for entry in scandir(folder):
    if entry.is_dir():
        # do code or skip
        continue
    myfile = folder + entry.name
    #do something with myfile

    
person user22996    schedule 26.01.2021