Как мне прочитать количество файлов в папке, используя Python?
Чтобы пересчитать файлы и каталоги нерекурсивно, вы можете использовать os.listdir и взять свою длину. Чтобы подсчитать файлы и каталоги рекурсивно, вы можете использовать os.walk для перебора файлов и подкаталогов в каталоге. Если вы хотите только сосчитать файлы, которые не являются каталогами, вы можете использовать os.listdir и os.path.file , чтобы проверить, является ли каждая запись файлом:
import os.path path = '.' num_files = len([f for f in os.listdir(path) if os.path.isfile(os.path.join(path, f))])
Или, альтернативно, используя генератор:
num_files = sum(os.path.isfile(os.path.join(path, f)) for f in os.listdir(path))
Или вы можете использовать os.walk следующим образом:
len(os.walk(path).next()[2])
Я нашел некоторые из этих идей из этот поток.
Mark Byers 07 окт. 2010, в 17:21
Поделиться
Вы можете использовать модуль glob:
>>> import glob >>> print len(glob.glob('/tmp/*')) 10
Или, как предлагает Марк Байерс в своем ответе, если вы хотите только файлы:
>>> print [f for f in glob.glob('/tmp/*') if os.path.isfile(f)] ['/tmp/foo'] >>> print sum(os.path.isfile(f) for f in glob.glob('/tmp/*')) 1
bstpierre 07 окт. 2010, в 17:53
Поделиться
Следует отметить, что os.listdir(‘.’) скрытые файлы (начиная с одной точки), а glob(‘./*’) — нет.
lunaryorn 07 окт. 2010, в 17:23
@lunaryorn — если вы хотите скрытые файлы в текущем каталоге, используйте glob(‘.*’) . Если вы хотите все, включая скрытые файлы, используйте glob(‘.*’) + glob(‘*’) .
bstpierre 07 окт. 2010, в 19:16
Ответ Марка Байера прост, изящный и сочетается с духом питона.
Есть проблема, однако: если вы попытаетесь запустить ее для любой другой директории, чем «.», она не будет работать, поскольку os.listdir() возвращает имена файлов, а не полный путь. Эти два значения совпадают при перечислении текущего рабочего каталога, поэтому ошибка не обнаруживается в исходном файле выше.
Например, если вы в «/home/me» и вы перечислите «/tmp», вы получите (скажем) [‘flashXVA67’]. Вы будете тестировать «/home/me/flashXVA67» вместо «/tmp/flashXVA67» с помощью метода выше.
Вы можете исправить это, используя os.path.join(), например:
import os.path path = './whatever' count = len([f for f in os.listdir(path) if os.path.isfile(os.path.join(path, f))])
Кроме того, если вы собираетесь делать этот счет много и требуют производительности, вы можете сделать это без создания дополнительных списков. Здесь менее элегантное, нерегулярное, но эффективное решение:
import os def fcount(path): """ Counts the number of files in a directory """ count = 0 for f in os.listdir(path): if os.path.isfile(os.path.join(path, f)): count += 1 return count # The following line prints the number of files in the current directory: path = "./whatever" print fcount(path)
Рекурсивное получение имен файлов по шаблону из дерева каталогов
Описанные ниже методы позволяют произвести рекурсивный обход дерева каталога и получить список файлов средствами модуля pathlib . Данные методы принадлежат экземпляру, созданному из класса Path() .
Так как класс pathlib.Path() наследуется от класса pathlib.PurePath() , следовательно он поддерживает все операции по манипуляции с путями файловой системы.
Содержание:
- Выбрать файлы из каталога в соответствии с шаблоном,
- Рекурсивный отбор файлов из каталога по шаблону,
- Получение итератора содержимого каталога.
Path.glob(pattern, *, case_sensitive=None) :
Метод Path.glob() возвращает список всех файлов любого типа, соответствующий заданному шаблону pattern , расположенных в каталоге, указанном в пути path .
>>> from pathlib import Path >>> paths = sorted(Path('.').glob('*.py')) >>> paths # [PosixPath('pthlib.py'), PosixPath('setup.py'), PosixPath('test_pathlib.py')] # преобразуем в список строк list(map(str, paths)) # ['pthlib.py', 'setup.py', 'test_pathlib.py'] >>> path = sorted(Path('.').glob('*/*.py')) >>> path # [PosixPath('docs/conf.py')] # что бы преобразовать объект PosixPath в строку # просто передайте его в функцию str() >>> str(path) # 'docs/conf.py'
Изменено в Python 3.11: возвращает только каталоги, если шаблон pattern заканчивается разделителем компонентов пути ( os.sep или os.altsep ).
Изменено в версии Python 3.12: Добавлен ключевой аргумент case_sensitivity . По умолчанию или когда аргументу case_sensitive присвоено значение None , этот метод сопоставляет пути, используя правила оформления, зависящие от конкретной платформы: как правило, с учетом регистра в POSIX и без учета регистра в Windows. Чтобы переопределить такое поведение, необходимо установить значение case_sensitive равным True или False .
Шаблоны pattern те же, что и для fnmatch , с добавлением «**» , что означает «этот каталог и все подкаталоги рекурсивно«. Другими словами, шаблон ‘**’ указывает на рекурсивный обход каталога в глубину, указанного в пути path , и всех его подкаталогов:
>>> from pathlib import Path >>> paths = sorted(Path('.').glob('**/*.py')) >>> paths # [PosixPath('build/lib/pathlib.py'), # PosixPath('docs/conf.py'), # PosixPath('pathlib.py'), # PosixPath('setup.py'), # PosixPath('test_pathlib.py')] # преобразуем в список строк >>> list(map(str, paths)) # ['build/lib/pathlib.py', # docs/conf.py, # pathlib.py, # 'setup.py' # 'test_pathlib.py']
Примечание. Использование шаблона ‘**’ в больших деревьях каталогов может занять слишком много времени.
Path.rglob(pattern, *, case_sensitive=None) :
Метод Path.rglob() работает подобно вызову метода Path.glob() с добавлением конструкции ‘**/’ перед заданным относительным шаблоном pattern , тем самым по умолчанию производит рекурсивный поиск файлов, соответствующих pattern :
>>> from pathlib import Path >>> sorted(Path().rglob("*.py")) # [PosixPath('build/lib/pathlib.py'), # PosixPath('docs/conf.py'), # PosixPath('pathlib.py'), # PosixPath('setup.py'), # PosixPath('test_pathlib.py')]
Изменено в версии Python 3.11: возвращает только каталоги, если шаблон pattern заканчивается разделителем компонентов пути ( os.sep или os.altsep ).
Изменено в версии Python 3.12: Добавлен ключевой аргумент case_sensitivity . По умолчанию или когда аргументу case_sensitive присвоено значение None , этот метод сопоставляет пути, используя правила оформления, зависящие от конкретной платформы: как правило, с учетом регистра в POSIX и без учета регистра в Windows. Чтобы переопределить такое поведение, необходимо установить значение case_sensitive равным True или False .
Path.iterdir() :
Метод Path.iterdir() вернет итератор объектов пути содержимого каталога, если путь path указывает на каталог:
>>> from pathlib import Path >>> p = Path('docs') >>> for child in p.iterdir(): str(child) . # 'docs/conf.py' # 'docs/_templates' # 'docs/make.bat' # 'docs/index.rst' # 'docs/_build' # 'docs/_static' # 'docs/Makefile'
Смотрите другие методы и свойства, доступные экземпляру класса Path() модуля pathlib .
- os.listdir() — список файлов в директории/каталоге,
- os.scandir() — информация о всех файлах в каталоге/директории,
- glob.glob() — рекурсивный поиск файлов по шаблону,
- os.walk() — рекурсивный обход каталога как в глубину, так и из глубины.
- КРАТКИЙ ОБЗОР МАТЕРИАЛА.
- Класс pathlib.PurePath() и его подклассы
- Класс pathlib.Path() и его подклассы
- Манипуляции с путями файловой системы средствами pathlib
- Проверить наличие файла/каталога/ссылки и т.д. средствами pathlib
- Открытие файла, чтение и запись информации средствами pathlib
- Определение положения в файловой системе средствами pathlib
- Список файлов в папке/каталоге по шаблону средствами pathlib
- Создание/удаление файла/каталога или ссылки средствами pathlib
- Получение информации о файле/каталоге средствами pathlib
- Изменение режима доступа к файлу или каталогу средствами pathlib
- Переименование/замена файла или каталога средствами pathlib
- Преобразование объекта пути pathlib в строку
- Метод walk() модуля pathlib, рекурсивный обход каталога
- Сравнение pathlib с модулями os и os.path
Как посчитать количество объектов (файлов и папок) в папке?
Имееется ввиду использование класса Path() , но не обязательно.
Вот такое решение мне кажется громоздким. Нет ли чего-то изящнее?
Задача решалась 100500 раз, видно плохо гуглил.
from pathlib import Path folder_name = input("folder name:") folder = Path(folder_name) if folder.is_dir(): folder_count = len([1 for file in folder.iterdir()]) print(f"В папке есть объектов")
Отслеживать
51.6k 200 200 золотых знаков 61 61 серебряный знак 243 243 бронзовых знака
Получение списка файлов в директории на Python

Всё чаще современные программисты предпочитают работать с языком программирования Python, потому что он очень гибкий, позволяющий легко взаимодействовать с операционной системой. Он также поставляется с функциями по работе с файловой системой. Решение задачи распечатки списка файлов в директории можно решить используя разные модули: os, subprocess, fnmatch и pathlib. Следующие решения демонстрируют, как успешно воспользоваться этими модулями.
Применение os.walk()
Модуль os содержит длинный список методов, которые касаются работы с файловой системой и операционной системой. Один из них walk(), возвращающий имена файлов в дереве каталогов, двигаясь по дереву сверху вниз или снизу вверх (сверху вниз по умолчанию).
os.walk() возвращает список из трех элементов: имя корневого каталога, список имен вложенных папок и список файлов в текущем каталоге. Он одинаково хорошо работает с интерпретаторами Python 2 и 3.
import os for root, dirs, files in os.walk("."): for filename in files: print(filename)
Использование командной строки, через subprocess
Модуль subprocess позволяет выполнить системную команду и собрать её результат. В нашем случае вызываемая системная команда выглядит следующим образом:
$ ls -p . | grep -v /$
Инструкция ls -p . распечатывает список файлов текущего каталога, добавляя разделитель / в конце имени каждого подкаталога, которые нам понадобится на следующем шаге. Вывод этого вызова передается команде grep, которая отфильтровывает данные по мере поступления. Параметры -v / $ исключают все имена записей, которые заканчиваются разделителем /. Фактически / $ — регулярное выражение, которое соответствует всем строкам, содержащим символ / самым последним символом в строке, который определяется символом $.
Модуль subprocess позволяет строить настоящие конвейеры, а также соединять входные и выходные потоки, как это делается в командной строке. Вызов метода subprocess.Popen() открывает соответствующий процесс и определяет два параметра stdin и stdout.
Первая переменная ls определяет процесс выполнения ls –p для захвата stdout в конвейере. Поэтому поток stdout определяется как subprocess.PIPE. Вторая переменная grep также определяется как процесс, но вместо этого выполняет инструкцию grep –v /$.
Чтобы прочитать вывод команды ls из конвейера, поток stdin grep присваиваивается в ls.stdout. В заключение, переменная endOfPipe считывает вывод команды grep из grep.stdout, затем распечатывается в stdout циклом for.
import subprocess # определение команды ls ls = subprocess.Popen(["ls", "-p", "."], stdout=subprocess.PIPE, ) # определение команды grep grep = subprocess.Popen(["grep", "-v", "/$"], stdin=ls.stdout, stdout=subprocess.PIPE, ) # чтение из данных из потока stdout endOfPipe = grep.stdout # распечатка файлов в строку for line in endOfPipe: print(line)
$ python find-files3.py find-files2.py find-files3.py find-files4.py .
Данное решение работает достаточно хорошо с Python 2 и 3, но его можно улучшить. Рассмотрим другие варианты.
Комбинация os и fnmatch
Решение, использующее подпроцессы, элегантно, но требует большого количества кода. Вместо этого, давайте объединим методы из двух модулей os и fnmatch. Этот вариант также работает с Python 2 и 3.
В качестве первого шага, импортируем модули os и fnmatch. Далее определим каталог, в котором нужно перечислить файлы, используя os.listdir(), а также шаблон для фильтрации файлов. В цикле for выполняется итерация списка записей, хранящихся в переменной listOfFiles.
В завершение, с помощью fnmatch отфильтровываются искомые записи и распечатываются соответствующие записи в stdout.
import os, fnmatch listOfFiles = os.listdir('.') pattern = "*.py" for entry in listOfFiles: if fnmatch.fnmatch(entry, pattern): print(entry)
$ python find-files.py find-files.py find-files2.py find-files3.py .
Использование os.listdir() и генераторов
Следующий вариант объединяет метод os.listdir() с функцией генератором. Код работает как с версиями 2, так и с 3 Python.
Как уже было сказано ранее, listdir() возвращает список записей для данного каталога. Метод os.path.isfile() возвращает True, если данная запись является файлом. Оператор yield завершает работу функции, но сохраняя текущее состояние и возвращает только имя записи являющейся файлом.
import os def files(path): for file in os.listdir(path): if os.path.isfile(os.path.join(path, file)): yield file for file in files("."): print(file)
Использование pathlib
Модуль pathlib предназначен для парсинга, сборки, тестирования и иной работы с именами файлов и их путями, используя объектно-ориентированный API вместо низкоуровневых строковых операций. Начиная с Python 3 модуль находится в стандартной библиотеке.
В следующем листинге определяется текущий каталог точкой («.»). Затем метод iterdir() возвращает итератор, который возвращает имена всех файлов. Далее циклом for распечатываются имена файлов друг за другом.
import pathlib # определение пути currentDirectory = pathlib.Path('.') for currentFile in currentDirectory.iterdir(): print(currentFile)
В качестве альтернативы, можно отфильтровать файлы по именам с помощью метода glob. Таким образом, получаем требуемые файлы. Например, в приведенном ниже коде перечисляются Python файлы в выбранном каталоге, указав шаблон «*.py» в glob.
import pathlib # определение пути currentDirectory = pathlib.Path('.') # определение шаблона currentPattern = "*.py" for currentFile in currentDirectory.glob(currentPattern): print(currentFile)
Использование os.scandir()
В Python 3.6 добавлен новый метод scandir(), доступный из модуля os. Как понятно из названия он значительно упрощает получение списка файлов в каталоге.
Чтобы определить текущий рабочий каталог и сохранить его, инициализируем значение переменной path, для этого импортируем модуль os и вызовем функцию getcwd(). Далее, scandir() возвращает список записей для выбранного пути, которые проверяются на принадлежность файлу, используя метод is_file().
import os # определение текущей рабочей директории path = os.getcwd() # чтение записей with os.scandir(path) as listOfEntries: for entry in listOfEntries: # печать всех записей, являющихся файлами if entry.is_file(): print(entry.name)
Вывод
Ведутся споры, какой вариант является лучшим, какой наиболее элегантным и какой является наиболее «питоничным». Мне нравится простота метода os.walk(), а также модули fnmatch и pathlib.
Две версии с процессами/конвейером и итератором требуют более глубокого понимания процессов UNIX и знаний Python, поэтому они не могут быть предпочтительными для всех программистов из-за их дополнительной (и избыточной) сложности.
Чтобы найти ответ на этот вопрос, выберем самой быстрой из них, воспользовавшись удобным модулем timeit. Данный модуль подсчитывает время, прошедшее между двумя событиями.
Для сравнения всех решений без их изменений, воспользуемся функциональностью Python: вызовем интерпретатор с модулем timeit и соответствующим Python скриптом. Для автоматизации процесса напишем shell скрипт
#! /bin/bash for filename in *.py; do echo "$filename:" cat $filename | python3 -m timeit echo " " done
Тесты проводились с использованием Python 3.6. Среди всех тестов os.walk() показала себя наилучшим образом. Выполнение тестов с помощью Python 2 возвращает разные значения, но os.walk() по-прежнему находится на вершине списка.