Как получить список всех файлов в каталоге с помощью Python
Оглавление
- Получение списка всех файлов и папок в каталоге на Python
- Рекурсивное перечисление с помощью .rglob()
- Использование шаблона Python Glob для условного перечисления
- Отказ от включения в список нежелательных каталогов
- Заключение
- Часто задаваемые вопросы
Смотрите сейчас, к этому уроку прилагается соответствующий видеокурс, созданный командой Real Python. Просмотрите его вместе с письменным руководством, чтобы углубить свое понимание: Список всех файлов в каталоге с помощью Python
Чтобы получить все файлы в каталоге с помощью Python, вы можете использовать модуль pathlib. В этом руководстве рассказывается, как использовать такие методы, как .iterdir(), .glob(), и .rglob(), для отображения содержимого каталога.
Для получения прямого списка файлов и папок вы используете .iterdir(). Методы .glob() и .rglob() поддерживают шаблоны глобализации для фильтрации файлов с определенными расширениями или именами. Для расширенной фильтрации вы можете комбинировать эти методы с функциями понимания или фильтрации.
К концу этого урока вы поймете, что можете:
- Список всех файлов каталога в Python с использованием
pathlib.Path().iterdir() - Найдите все файлы с определенным расширением с помощью
pathlib.Path().glob("*.extension") - Используйте
pathlib.Path().rglob("*")для рекурсивного поиска всех файлов в каталоге и его подкаталогах
В модуле pathlib вы познакомитесь с наиболее универсальными методами составления списка элементов в каталоге, но вы также узнаете немного о некоторых альтернативных инструментах.
Исходный код: Нажмите здесь, чтобы бесплатно загрузить исходный код, каталоги и дополнительные материалы, которые демонстрируют различные способы отображения списка файлов и папок в каталоге с помощью Python.
До выхода pathlib в Python 3.4, если вы хотели работать с путями к файлам, то использовали модуль os. Хотя это было очень эффективно с точки зрения производительности, вам приходилось обрабатывать все пути как строк.
Сначала обработка путей в виде строк может показаться простой, но как только вы начинаете использовать несколько операционных систем, все становится сложнее. В итоге вы также получаете кучу кода, связанного с манипуляцией строками, который может сильно отличаться от того, что такое путь к файлу. Все может стать загадочным довольно быстро.
Примечание: Ознакомьтесь с загружаемыми материалами для некоторых тестов, которые вы можете запустить на своем компьютере. Тесты будут сравнивать время, необходимое для получения списка всех элементов в каталоге, используя методы из модуля pathlib, модуля os и даже из Python 3.12 версия pathlib. Эта версия включает в себя хорошо известную функцию walk(), о которой вы не будете рассказывать в этом руководстве.
Это не значит, что работа с путями в виде строк невозможна — в конце концов, разработчики прекрасно обходились без pathlib в течение многих лет! Модуль pathlib просто решает множество сложных задач и позволяет вам сосредоточиться на основной логике вашего кода.
Все начинается с создания Path объекта, который будет отличаться в зависимости от вашей операционной системы (OS). В Windows вы получите объект WindowsPath, в то время как Linux и macOS вернут PosixPath:
>>> import pathlib >>> desktop = pathlib.Path("C:/Users/RealPython/Desktop") >>> desktop WindowsPath("C:/Users/RealPython/Desktop")предварительно> кодовый блок>>>> import pathlib >>> desktop = pathlib.Path("/home/RealPython/Desktop") >>> desktop PosixPath('/home/RealPython/Desktop')предварительно> кодовый блок>С помощью этих объектов, поддерживающих работу с операционной системой, вы можете воспользоваться множеством доступных методов и свойств, например, для получения списка файлов и папок.
примечание: Если вы заинтересованы в получении дополнительной информации о
pathlibи его особенности, а затем проверить в Python pathlib модуль: Укрощение системный файл иpathlibдокументация.Теперь пришло время перейти к перечислению содержимого папки. Имейте в виду, что существует несколько способов сделать это, и выбор правильного из них будет зависеть от вашего конкретного случая использования.
Получение списка всех файлов и папок в каталоге на Python
Прежде чем приступить к составлению списка, вам понадобится набор файлов, соответствующий тому, с которым вы столкнетесь в этом руководстве. В дополнительных материалах вы найдете папку с названием Рабочий стол. Если вы планируете продолжить, загрузите эту папку и перейдите в родительскую папку и запустите свой Python REPL там:
Исходный код: Нажмите здесь, чтобы бесплатно загрузить исходный код, каталоги и дополнительные материалы, которые демонстрируют различные способы отображения списка файлов и папок в каталоге с помощью Python.
Вы также можете использовать свой собственный рабочий стол. Просто запустите Python REPL в родительском каталоге вашего рабочего стола, и примеры должны сработать, но вместо этого в выходных данных у вас будут ваши собственные файлы.
Примечание: В этом руководстве вы в основном увидите
WindowsPathобъектов в качестве выходных данных. Если вы используете Linux или macOS, то вместо этого увидитеPosixPath. Это будет единственное отличие. Код, который вы пишете, одинаков на всех платформах.Если вам нужно только перечислить содержимое данного каталога, и вам не нужно получать содержимое каждого подкаталога, то вы можете использовать
Pathметод объекта.iterdir(). Если ваша цель - рекурсивно перемещаться по каталогам и подкаталогам , то вы можете перейти к разделу , посвященному рекурсивному перечислению.Метод
.iterdir(), вызываемый для объектаPath, возвращает генератор, который выдаетPathобъектов, представляющих дочерние элементы. Если вы обернете генератор в конструкторlist(), то сможете увидеть свой список файлов и папок:>>> import pathlib >>> desktop = pathlib.Path("Desktop") >>> # .iterdir() produces a generator >>> desktop.iterdir() <generator object Path.iterdir at 0x000001A8A5110740> >>> # Which you can wrap in a list() constructor to materialize >>> list(desktop.iterdir()) [WindowsPath('Desktop/Notes'), WindowsPath('Desktop/realpython'), WindowsPath('Desktop/scripts'), WindowsPath('Desktop/todo.txt')]предварительно> кодовый блок>При передаче генератора, созданного
.iterdir(), в конструкторlist()вы получите списокPathобъектов, представляющих все элементы на рабочем столе каталог.Как и во всех генераторах, вы также можете использовать цикл
forдля перебора каждого элемента, который выдает генератор. Это дает вам возможность изучить некоторые свойства каждого объекта:>>> desktop = pathlib.Path("Desktop") >>> for item in desktop.iterdir(): ... print(f"{item} - {'dir' if item.is_dir() else 'file'}") ... Desktop\Notes - dir Desktop\realpython - dir Desktop\scripts - dir Desktop\todo.txt - fileпредварительно> кодовый блок>В теле цикла
forиспользуется f-строка для отображения некоторой информации о каждом элементе.Во втором наборе фигурных скобок (
{}) в f-строке вы используете условное выражение для вывода dir если элемент является каталогом, или файлом, если это не так. Чтобы получить эту информацию, вы используете метод.is_dir().Помещение объекта
Pathв f-строку автоматически преобразует объект в строку, поэтому у вас больше нет аннотацииWindowsPathилиPosixPath.Преднамеренное повторение объекта с помощью цикла
for, подобного этому, может быть очень удобно для фильтрации по файлам или каталогам, как в следующем примере:>>> desktop = pathlib.Path("Desktop") >>> for item in desktop.iterdir(): ... if item.is_file(): ... print(item) ... Desktop\todo.txtпредварительно> кодовый блок>Здесь вы используете условный оператор и метод
.is_file(), чтобы напечатать элемент только в том случае, если это файл.Вы также можете поместить генераторы в представления, что может привести к очень сжатому коду:
>>> desktop = pathlib.Path("Desktop") >>> [item for item in desktop.iterdir() if item.is_dir()] [WindowsPath('Desktop/Notes'), WindowsPath('Desktop/realpython'), WindowsPath('Desktop/scripts')]предварительно> кодовый блок>Здесь вы фильтруете результирующий список, используя условное выражение внутри понимания, чтобы проверить, является ли элемент каталогом.
Но что, если вам тоже нужны все файлы и каталоги в подкаталогах вашей папки? Вы можете адаптировать
.iterdir()как рекурсивную функцию, как вы сделаете позже в руководстве, но, возможно, вам лучше использовать.rglob(), к которому вы перейдете далее.Рекурсивное перечисление С помощью
.rglob()Каталоги часто сравнивают с деревьями из-за их рекурсивной природы. В деревьях главный ствол разделяется на различные главные ветви. Каждая главная ветвь разделяется на дополнительные ответвления. Каждая подотрасль также ответвляется сама от себя, и так далее. Аналогично, каталоги содержат подкаталоги, которые содержат подкаталоги, которые содержат еще несколько подкаталогов, и так далее.
Рекурсивное перечисление элементов в каталоге означает перечисление не только содержимого каталога, но и содержимого подкаталогов, их подкаталогов и так далее.
С помощью
pathlibна удивление легко выполнить рекурсивный поиск по каталогу. Вы можете использовать.rglob()для возврата абсолютно всего:>>> import pathlib >>> desktop = pathlib.Path("Desktop") >>> # .rglob() produces a generator too >>> desktop.rglob("*") <generator object Path.glob at 0x000001A8A50E2F00> >>> # Which you can wrap in a list() constructor to materialize >>> list(desktop.rglob("*")) [WindowsPath('Desktop/Notes'), WindowsPath('Desktop/realpython'), WindowsPath('Desktop/scripts'), WindowsPath('Desktop/todo.txt'), WindowsPath('Desktop/Notes/hash-tables.md'), WindowsPath('Desktop/realpython/iterate-dict.md'), WindowsPath('Desktop/realpython/tictactoe.md'), WindowsPath('Desktop/scripts/rename_files.py'), WindowsPath('Desktop/scripts/request.py')]предварительно> кодовый блок>Метод
.rglob()с"*"в качестве аргумента создает генератор, который рекурсивно возвращает все файлы и папки из объектаPath.Но что это за аргумент asterisk для
.rglob()? В следующем разделе вы рассмотрите шаблоны глобальных объектов и увидите, как можно сделать нечто большее, чем просто перечислить все элементы в каталоге.Использование шаблона Python Glob для условного перечисления
Иногда вам не нужны все файлы. Бывают случаи, когда вам нужен только один тип файла или каталога, или, возможно, все элементы с определенным набором символов в названии.
Методом, связанным с
.rglob(), является метод.glob(). Оба этих метода используют шаблоны glob. Глобулярный шаблон представляет собой набор путей. Глобулярные шаблоны используют подстановочных знаков для соответствия определенным критериям. Например, единственная звездочка*соответствует всему, что есть в каталоге.Существует множество различных шаблонов глобусов, которыми вы можете воспользоваться. Ознакомьтесь со следующей подборкой шаблонов глобусов, чтобы получить некоторые идеи:
Glob Pattern Matches *Every item *.txtEvery item ending in .txt, such asnotes.txtorhello.txt??????Every item whose name is six characters long, such as 01.txt,A-01.c, or.zshrcA*Every item that starts with the character A, such as Album,A.txt, orAppData[abc][abc][abc]Every item whose name is three characters long but only composed of the characters a, b, and c, such as abc,aaa, orcbaС помощью этих шаблонов вы можете гибко сопоставлять множество различных типов файлов. Ознакомьтесь с документацией по
fnmatch,, которая является базовым модулем, управляющим поведением.glob(), чтобы получить представление о других шаблонах, которые вы можете использовать в Python.Обратите внимание, что в Windows шаблоны глобальных объектов не учитывают регистр, поскольку пути в целом не учитывают регистр символов. В Unix-подобных системах, таких как Linux и macOS, шаблоны глобальных объектов чувствительны к регистру.
Условный список с использованием
.glob()Метод
.glob()объектаPathведет себя во многом так же, как и.rglob(). Если вы передадите аргумент"*", то получите список элементов в каталоге, но без рекурсии:>>> import pathlib >>> desktop = pathlib.Path("Desktop") >>> # .glob() produces a generator too >>> desktop.glob("*") <generator object Path.glob at 0x000001A8A50E2F00> >>> # Which you can wrap in a list() constructor to materialize >>> list(desktop.glob("*")) [WindowsPath('Desktop/Notes'), WindowsPath('Desktop/realpython'), WindowsPath('Desktop/scripts'), WindowsPath('Desktop/todo.txt')]предварительно> кодовый блок>При использовании метода
.glob()с шаблоном"*"для объектаPathсоздается генератор, который выдает все элементы в каталоге, представленныеPathобъект, не заходя в подкаталоги. Таким образом, он выдает тот же результат, что и.iterdir(), и вы можете использовать результирующий генератор в циклеforили для понимания, точно так же, как вы бы использовали сiterdir().Но, как вы уже узнали, что действительно отличает методы glob друг от друга, так это различные шаблоны, которые вы можете использовать для сопоставления только определенных путей. Например, если вам нужны только те пути, которые заканчиваются на
.txt, то вы могли бы сделать следующее:>>> desktop = pathlib.Path("Desktop") >>> list(desktop.glob("*.txt")) [WindowsPath('Desktop/todo.txt')]предварительно> кодовый блок>Поскольку в этом каталоге есть только один текстовый файл, вы получите список, содержащий только один элемент. Если вы хотите получить только элементы, которые начинаются, например, с real, то вы могли бы использовать следующий шаблон глобуса:
>>> list(desktop.glob("real*")) [WindowsPath('Desktop/realpython')]предварительно> кодовый блок>В этом примере также отображается только один элемент, поскольку только одно имя элемента начинается с символов
real. Помните, что в Unix-подобных системах шаблоны глобусов чувствительны к регистру.Примечание: Имя здесь относится к последней части пути, а не к другим частям пути, которые в этом случае начинались бы с
Desktop.Вы также можете получить содержимое подкаталога, указав его название через косую черту (
/), и звездочка. Этот тип шаблона приведет к получению всего, что находится внутри целевого каталога:>>> list(desktop.glob("realpython/*")) [WindowsPath('Desktop/realpython/iterate-dict.md'), WindowsPath('Desktop/realpython/tictactoe.md')]предварительно> кодовый блок>В этом примере при использовании шаблона
"realpython/*"будут получены все файлы в каталогеrealpython. Это даст вам тот же результат, что и создание объекта path, представляющего путьDesktop/realpython, и вызов.glob("*")по нему.Далее вы немного подробнее рассмотрите фильтрацию с помощью
.rglob()и узнаете, чем она отличается от.glob().Условный список с использованием
.rglob()Точно так же, как и в случае с методом
.glob(), вы можете настроить шаблон глобуса для.rglob(), чтобы он давал вам только определенное расширение файла, за исключением того, что.rglob()всегда будет выполнять рекурсивный поиск:>>> list(desktop.rglob("*.md")) [WindowsPath('Desktop/Notes/hash-tables.md'), WindowsPath('Desktop/realpython/iterate-dict.md'), WindowsPath('Desktop/realpython/tictactoe.md')]предварительно> кодовый блок>Добавляя
.mdк шаблону glob, теперь.rglob()создает только.mdфайлов в разных каталогах и подкаталогах.На самом деле вы можете использовать
.glob()и заставить его вести себя так же, как.rglob(), изменив шаблон glob, передаваемый в качестве аргумента:>>> list(desktop.glob("**/*.md")) [WindowsPath('Desktop/Notes/hash-tables.md'), WindowsPath('Desktop/realpython/iterate-dict.md'), WindowsPath('Desktop/realpython/tictactoe.md')]предварительно> кодовый блок>В этом примере вы можете видеть, что вызов
.glob("**/*.md")эквивалентен.rglob(*.md). Аналогично, вызов.glob("**/*")эквивалентен.rglob("*").Метод
.rglob()представляет собой несколько более явную версию вызова.glob()с рекурсивным шаблоном, поэтому, вероятно, лучше использовать более явную версию вместо использования рекурсивных шаблонов с обычным.glob().Расширенное сопоставление с глобальными методами
Одним из потенциальных недостатков глоб-методов является то, что вы можете выбирать файлы только на основе шаблонов глоб-объектов. Если вы хотите выполнить более сложное сопоставление или фильтрацию по атрибутам элемента, вам нужно найти что-то дополнительное.
Чтобы выполнить более сложное сопоставление и фильтрацию, вы можете воспользоваться как минимум тремя стратегиями. Вы можете использовать:
- Цикл
forс условной проверкой- Понимание с помощью условного выражения
- Встроенная функция
filter()Вот как это делается:
>>> import pathlib >>> desktop = pathlib.Path("Desktop") >>> # Using a for loop >>> for item in desktop.rglob("*"): ... if item.is_file(): ... print(item) ... Desktop\todo.txt Desktop\Notes\hash-tables.md Desktop\realpython\iterate-dict.md Desktop\realpython\tictactoe.md Desktop\scripts\rename_files.py Desktop\scripts\request.py >>> # Using a comprehension >>> [item for item in desktop.rglob("*") if item.is_file()] [WindowsPath('Desktop/todo.txt'), WindowsPath('Desktop/Notes/hash-tables.md'), WindowsPath('Desktop/realpython/iterate-dict.md'), WindowsPath('Desktop/realpython/tictactoe.md'), WindowsPath('Desktop/scripts/rename_files.py'), WindowsPath('Desktop/scripts/request.py')] >>> # Using the filter() function >>> list(filter(lambda item: item.is_file(), desktop.rglob("*"))) [WindowsPath('Desktop/todo.txt'), WindowsPath('Desktop/Notes/hash-tables.md'), WindowsPath('Desktop/realpython/iterate-dict.md'), WindowsPath('Desktop/realpython/tictactoe.md'), WindowsPath('Desktop/scripts/rename_files.py'), WindowsPath('Desktop/scripts/request.py')]предварительно> кодовый блок>В этих примерах сначала вызывается метод
.rglob()с шаблоном"*", чтобы рекурсивно получить все элементы. При этом создаются все элементы в каталоге и его подкаталогах. Затем вы используете три различных подхода, перечисленных выше, чтобы отфильтровать элементы, которые не являются файлами. Обратите внимание, что в случаеfilter(), вы использовали лямбда-функцию.Методы glob чрезвычайно универсальны, но для больших деревьев каталогов они могут быть немного медленными. В следующем разделе вы рассмотрите пример, в котором использование
.iterdir()может быть лучшим выбором для обеспечения более контролируемой итерации.Отказ от включения в список нежелательных каталогов
Допустим, например, что вы хотели найти все файлы в вашей системе, но у вас есть различные подкаталоги, в которых содержится множество подкаталогов и файлов. Некоторые из самых больших подкаталогов - это временные файлы, которые вас не интересуют.
Например, изучите это дерево каталогов, в котором есть ненужные каталоги — их много! На самом деле, это полное дерево каталогов состоит из 1850 строк. Везде, где вы видите многоточие (
...), это означает, что в этом месте находятся сотни ненужных файлов:
large_dir/ ├── documents/ │ ├── notes/ │ │ ├── temp/ │ │ │ ├── 2/ │ │ │ │ ├── 0.txt │ │ │ │ ... │ │ │ │ │ │ │ ├── 0.txt │ │ │ ... │ │ │ │ │ ├── 0.txt │ │ └── find_me.txt │ │ │ ├── tools/ │ │ ├── temporary_files/ │ │ │ ├── logs/ │ │ │ │ ├──0.txt │ │ │ │ ... │ │ │ │ │ │ │ ├── temp/ │ │ │ │ ├──0.txt │ │ │ │ ... │ │ │ │ │ │ │ ├── 0.txt │ │ │ ... │ │ │ │ │ ├── 33.txt │ │ ├── 34.txt │ │ ├── 36.txt │ │ ├── 37.txt │ │ └── real_python.txt │ │ │ ├── 0.txt │ ├── 1.txt │ ├── 2.txt │ ├── 3.txt │ └── 4.txt │ ├── temp/ │ ├── 0.txt │ ... │ └── temporary_files/ ├── 0.txt ...Проблема в том, что у вас есть ненужные каталоги. Иногда ненужные каталоги называются
temp, иногдаtemporary files, а иногдаlogs. Что еще хуже, так это то, что они есть везде и могут быть на любом уровне вложенности. Хорошая новость в том, что вам не нужно их перечислять, о чем вы узнаете далее.Использование
.rglob()для фильтрации целых каталоговЕсли вы используете
.rglob(), вы можете просто отфильтровать элементы, как только они будут созданы с помощью.rglob(). Чтобы правильно удалить пути, которые находятся в нежелательной директории, вы можете проверить, совпадает ли какой-либо из элементов пути с каким-либо из элементов в списке каталогов, которые следует пропустить:>>> SKIP_DIRS = ["temp", "temporary_files", "logs"]предварительно> кодовый блок>Здесь вы определяете
SKIP_DIRSкак список, содержащий строки путей, которые вы хотите исключить.Вызов
.rglob()со звездочкой в качестве аргумента приведет к созданию всех элементов, даже тех, которые находятся в каталогах, которые вас не интересуют. Поскольку вам нужно просмотреть все элементы, может возникнуть проблема, если вы посмотрите только на название пути:large_dir/documents/notes/temp/2/0.txtпредварительно> кодовый блок>Поскольку имя просто
0.txt, оно не будет соответствовать ни одному элементу вSKIP_DIRS. Вам нужно будет проверить весь путь на наличие заблокированного имени.Вы можете получить все элементы в пути с помощью атрибута
.parts, который содержит кортеж из всех элементов в пути:>>> import pathlib >>> temp_file = pathlib.Path("large_dir/documents/notes/temp/2/0.txt") >>> temp_file.parts ('large_dir', 'documents', 'notes', 'temp', '2', '0.txt')предварительно> кодовый блок>Затем все, что вам нужно сделать, это проверить, есть ли какой-либо элемент в кортеже
.partsв списке каталогов, которые нужно пропустить.Вы можете проверить, есть ли у каких-либо двух итераций общий элемент, воспользовавшись наборами. Если вы приведете одну из итераций к набору, то вы можете использовать метод
.isdisjoint(), чтобы определить, есть ли у них какие-либо общие элементы:>>> {"documents", "notes", "find_me.txt"}.isdisjoint({"temp", "temporary"}) True >>> {"documents", "temp", "find_me.txt"}.isdisjoint({"temp", "temporary"}) Falseпредварительно> кодовый блок>Если два набора не имеют общих элементов, то
.isdisjoint()возвращаетTrue. Если два набора имеют хотя бы один общий элемент, то.isdisjoint()возвращаетFalse. Вы можете включить эту проверку в циклfor, который обрабатывает все элементы, возвращаемые.rglob("*"):>>> SKIP_DIRS = ["temp", "temporary_files", "logs"] >>> large_dir = pathlib.Path("large_dir") >>> # With a for loop >>> for item in large_dir.rglob("*"): ... if set(item.parts).isdisjoint(SKIP_DIRS): ... print(item) ... large_dir\documents large_dir\documents\0.txt large_dir\documents\1.txt large_dir\documents\2.txt large_dir\documents\3.txt large_dir\documents\4.txt large_dir\documents\notes large_dir\documents\tools large_dir\documents\notes\0.txt large_dir\documents\notes\find_me.txt large_dir\documents\tools\33.txt large_dir\documents\tools\34.txt large_dir\documents\tools\36.txt large_dir\documents\tools\37.txt large_dir\documents\tools\real_python.txtпредварительно> кодовый блок>В этом примере вы печатаете все элементы в
large_dir, которых нет ни в одном из ненужных каталогов.Чтобы проверить, находится ли путь в одной из нежелательных папок, вы присваиваете
item.partsзначение set и используете.isdisjoint(), чтобы проверить, находятся лиSKIP_DIRSи.partsу нет никаких общих элементов. Если это так, то элемент будет напечатан.Вы также можете добиться того же эффекта с помощью
filter()и пояснений, как показано ниже:>>> # With a comprehension >>> [ ... item ... for item in large_dir.rglob("*") ... if set(item.parts).isdisjoint(SKIP_DIRS) ... ] >>> # With filter() >>> list( ... filter( ... lambda item: set(item.parts).isdisjoint(SKIP_DIRS), ... large_dir.rglob("*") ... ) ... )предварительно> кодовый блок>Однако эти методы уже становятся немного загадочными и им трудно следовать. Не только это, но и то, что они не очень эффективны, потому что генератор
.rglob()должен генерировать все элементы, чтобы операция сопоставления могла отменить этот результат.Вы определенно можете отфильтровать целые папки с помощью
.rglob(), но вы не можете уйти от того факта, что результирующий генератор выдаст все элементы, а затем отфильтрует все остальные. нежелательные, один за другим. Это может привести к тому, что методы glob будут работать очень медленно, в зависимости от вашего варианта использования. Вот почему вы можете выбрать рекурсивную функцию.iterdir(), которую мы рассмотрим далее.Создание рекурсивной функции
.iterdir()В примере с нежелательными каталогами в идеале требуется возможность отказаться от перебора всех файлов в данном подкаталоге, если они соответствуют одному из имен в
SKIP_DIRS:# skip_dirs.py import pathlib SKIP_DIRS = ["temp", "temporary_files", "logs"] def get_all_items(root: pathlib.Path, exclude=SKIP_DIRS): for item in root.iterdir(): if item.name in exclude: continue yield item if item.is_dir(): yield from get_all_items(item)предварительно> кодовый блок>В этом модуле вы определяете список строк
SKIP_DIRS, который содержит имена каталогов, которые вы хотели бы игнорировать. Затем вы определяете функцию генератора, которая использует.iterdir()для просмотра каждого элемента.Функция генератора использует аннотацию типа
: pathlib.Pathпосле первого аргумента, указывающего на то, что вы не можете просто передать строку, представляющую путь. Аргументом должен быть объектPath.Если название элемента находится в списке
exclude, вы просто переходите к следующему элементу, пропуская все дерево подкаталогов за один раз.Если элемента нет в списке, то вы возвращаете элемент, и если это каталог, вы снова вызываете функцию в этом каталоге. То есть в теле функции функция условно вызывает ту же функцию снова. Это отличительный признак рекурсивной функции.
Эта рекурсивная функция эффективно возвращает все нужные вам файлы и каталоги, исключая все, что вас не интересует:
>>> import pathlib >>> import skip_dirs >>> large_dir = pathlib.Path("large_dir") >>> list(skip_dirs.get_all_items(large_dir)) [WindowsPath('large_dir/documents'), WindowsPath('large_dir/documents/0.txt'), WindowsPath('large_dir/documents/1.txt'), WindowsPath('large_dir/documents/2.txt'), WindowsPath('large_dir/documents/3.txt'), WindowsPath('large_dir/documents/4.txt'), WindowsPath('large_dir/documents/notes'), WindowsPath('large_dir/documents/notes/0.txt'), WindowsPath('large_dir/documents/notes/find_me.txt'), WindowsPath('large_dir/documents/tools'), WindowsPath('large_dir/documents/tools/33.txt'), WindowsPath('large_dir/documents/tools/34.txt'), WindowsPath('large_dir/documents/tools/36.txt'), WindowsPath('large_dir/documents/tools/37.txt'), WindowsPath('large_dir/documents/tools/real_python.txt')]предварительно> кодовый блок>Самое главное, что вам удалось отказаться от проверки всех файлов в нежелательных каталогах. Как только ваш генератор определит, что каталог находится в списке
SKIP_DIRS, он просто пропустит все это.Таким образом, в этом случае использование
.iterdir()будет намного эффективнее, чем эквивалентные методы glob.На самом деле, вы обнаружите, что
.iterdir()обычно более эффективен, чем методы glob, если вам нужно отфильтровать что-либо более сложное, чем может быть достигнуто с помощью шаблона glob. Однако, если все, что вам нужно сделать, это рекурсивно получить список всех.txtфайлов, то методы glob будут работать быстрее.Ознакомьтесь с загружаемыми материалами для некоторых тестов, которые демонстрируют относительную скорость различных способов отображения списка файлов в Python:
Исходный код: Нажмите здесь, чтобы бесплатно загрузить исходный код, каталоги и дополнительные материалы, которые демонстрируют различные способы отображения списка файлов и папок в каталоге с помощью Python.
Имея в своем распоряжении эту информацию, вы будете готовы выбрать наилучший способ отображения списка файлов и папок, которые вам нужны!
Заключение
В этом руководстве вы изучили методы
.glob(),.rglob(), и.iterdir()из модуля Pythonpathlib, позволяющие получить список всех файлов и папок в заданном каталоге . Вы рассмотрели список файлов и папок, которые являются прямыми потомками каталога, а также рассмотрели рекурсивный список.В общем, вы видели, что если вам нужен просто базовый список элементов в каталоге, без рекурсии, то
.iterdir()- это самый простой метод для использования, благодаря его описательному названию. Это также более эффективно при выполнении этой работы. Однако, если вам нужен рекурсивный список, то лучше всего использовать.rglob(), который будет быстрее, чем эквивалентный рекурсивный.iterdir().Вы также рассмотрели один пример, в котором использование
.iterdir()для рекурсивного составления списка может значительно повысить производительность — когда у вас есть ненужные папки, от повторной обработки которых вы хотите отказаться.В загружаемых материалах вы найдете различные реализации методов получения базового списка файлов как из модулей
pathlib, так иos, а также пару скриптов, которые синхронизируют их все друг с другом:Исходный код: Нажмите здесь, чтобы бесплатно загрузить исходный код, каталоги и дополнительные материалы, которые демонстрируют различные способы отображения списка файлов и папок в каталоге с помощью Python.
Ознакомьтесь с ними, измените их и поделитесь своими находками в комментариях!
Часто задаваемые вопросы
Теперь, когда у вас есть некоторый опыт поиска всех файлов в каталоге с помощью Python, вы можете использовать вопросы и ответы, приведенные ниже, чтобы проверить свое понимание и резюмировать то, что вы узнали.
Эти часто задаваемые вопросы относятся к наиболее важным понятиям, которые вы рассмотрели в этом руководстве. Нажмите на переключатель Показывать/скрывать рядом с каждым вопросом, чтобы открыть ответ.
Вы можете использовать метод
Path.iterdir()из модуляpathlib, чтобы вывести список всех файлов в каталоге. Он предоставляет генератор, который вы можете преобразовать в список, чтобы увидеть все элементы.
Вы можете использовать методы
Path.glob()илиPath.rglob()с шаблоном типа*.txt, чтобы найти все файлы с определенным расширением, например.txt.
Вы можете использовать метод
<статус завершения article-slug="получить все файлы в каталоге python" class="btn-group mb-0" data-api-article-bookmark-url="/api/v1/articles/получить все файлы в каталоге python"/закладка/" data-api-article-completion-status-url="/api/v1/articles/get-all-files-in-directory-python/completion_status/"> статус завершения> <кнопка поделиться bluesky-text="Интересная статья на #Python от @realpython.com :" email-body="Ознакомьтесь с этой статьей о Python:%0A%0Ah Как получить список всех файлов в каталоге с Python" email-subject="Статья о Python для вас" twitter-текст="Интересная статья на #Python от @realpython:" url="https://realpython.com/get-all-files-in-directory-python/" url-title="Как получить список всех файлов в каталоге с помощью Python"> кнопка поделиться>Path.rglob("*")для рекурсивного поиска всех файлов в каталоге и его подкаталогах.Смотрите сейчас, к этому уроку прилагается соответствующий видеокурс, созданный командой Real Python. Просмотрите его вместе с письменным руководством, чтобы углубить свое понимание: Список всех файлов в каталоге с помощью Python
Back to Top