Как получить все файлы в папке python

от admin

Содержание папки

Модуль стандартной библиотеки os (от «operation system») предоставляет множество полезных функций для произведения системных вызовов. Одна из базовых функций этого модуля — os.listdir .

С точки зрения операционной системы нет разницы между файлом, папкой или другим подобным объектом, типа ссылки. Поэтому os.listdir() возвращает список как файлов, так и папок. Обратите внимание, что порядок элементов возвращаемого списка не регламентируется, если вам нужно их отсортировать не забудьте сделать это:

Работа с путями к файлам и папкам

Модуль os содержит подмодуль os.path , который позволяет работать с путями файлов и папок. Импортировать этот модуль отдельно не нужно, достаточно выполнить import os .

Присоединение одной части пути к другой

Работа с путями к файлам и папкам как с простыми строками чревата множеством ошибок и может создать проблемы при переносе программы между различными операционными системами. Правильный путь объединить две части пути — это использование os.path.join :

Извлечение имени файла из пути

Функция os.path.split совершает обратное действие — отрезает имя файла или ниже лежащей папки от пути:

Извлечение расширения

Кроме того, может пригодиться функция os.path.splitext , котоая отрезает расширение файла:

Проверка типа файла

Кроме прочего, модуль os.path содержит функции для проверки существования файла и для определения его типа:

Манипуляции с файлами и папками

Производите все манипуляции с файлами с осторожностью, придерживайтесь правила «семь раз отмерь — один раз отрежь». Не забывайте программно производить все возможные проверки перед выполнением операций.

Создание файла

Нет ничего проще, чем создать пустой файл, достаточно открыть несуществующий файл с флагом ‘x’ :

Конечно, можно было бы использовать флаг ‘w’ , но тогда уже существующий файл был бы стёрт. С флагом ‘x’ open либо создаст новый файл, либо выбросит ошибку.

Создание папки

Для создания новой папки используйте os.mkdir(name) . Эта функция выбросит ошибку, если по указанному пути уже существует файл или папка. Если вам нужно создать сразу несколько вложенных папок, то смотрите функцию os.makedirs(name, exist_ok=False) .

Перемещение и переименование

Для удобной манипуляции с файлами и папками в стандартной библиотеки Python существует специальный модуль shutil . Функция shutil.move(source, destination) позволяет вам переместить любой файл или папку (даже непустую). Обратите внимание, что если destination — это уже существующая папка, то файл/папка будет перемещена внутрь неё, в остальных случаях файл/папка будут скопированы точно по нужному адресу. В случае успеха, функция вернёт новое местоположение файла. Если destination существует и не является папкой, то будет выброшена ошибка.

Как же переименовать файл? Несмотря на то, что os содержит специальную функцию для переименования, нужно понимать, что в рамках одной файловой системы перемещение и переименование — это одно и то же. Когда вы переименовываете файл, его содержимое не переписывается на носителе в другое место, просто файловая система теперь обозначает его положение другим путём.

Копирование

Скопировать файл можно с помощью функции shutil.copy(source, destination) . Правила расположения копии будут те же, что и при использовании shutil.move , за тем исключением, что если destination существует и не является файлом, то он будет заменён и ошибки это не вызовет.

Скопировать папку для операционной системы сложнее, ведь мы всегда хотим скопировать не только папку, но и её содержимое. Для копирования папок используйте shutil.copytree(source, destination) . Обратите внимание, что для этой функции destination всегда должно быть путём конечного расположения файлов и не может быть уже существующей папкой.

Удаление

Удалить файл можно с помощью функции os.remove , а пустую папку с помощью функции os.rmdir .

А вот для удаления папки с содержимым вновь понадобится shutil . Для удаления такой папки используйте shutil.rmtree .

Будьте осторожны, команды удаления стирают файл, а не перемещают его в корзину, вне зависимости от операционной системы! После такого удаления восстановить файл может быть сложно или вовсе невозможно.

Домашняя работа

  1. В текущей папке лежат файлы с расширениями .mp3 , .flac и .oga . Создайте папки mp3 , flac , oga и положите туда все файлы с соответствующими расширениями.
  2. В текущей папке лежит две других папки: vasya и mila , причём в этих папках могут лежать файлы с одинаковыми именами, например vasya/kursovaya.doc и mila/kursovaya.doc . Скопируйте все файлы из этих папок в текущую папку назвав их следующим образом: vasya_kursovaya.doc , mila_test.pdf и т.п.
  3. В текущей папке лежат файлы следующего вида: S01E01.mkv , S01E02.mkv , S02E01.mkv и т.п., то есть все файлы начинаются с S01 или S02 . Создайте папки S01 и S02 и переложите туда соответствующие файлы.
  4. В текущей папке лежат файлы вида 2019-03-08.jpg , 2019-04-01.jpg и т.п. Отсортируйте файлы по имени и переименуйте их в 1.jpg , 2.jpg , …, 10.jpg , и т.д.
  5. В текущей папке лежат две другие папки: video и sub . Создайте новую папку watch_me и переложите туда содержимое указанных папок (сами папки класть не надо).
  6. В текущей папке лежат файлы типа Nina_Stoletova.jpg , Misha_Perelman.jpg и т.п. Переименуйте их переставив имя и фамилию местами.
  7. В текущей папке лежит файл list.tsv , в котором с новой строки написаны имена некоторых других файлов этой папки. Создайте папку list и переложите в неё данные файлы.

Для тестирования вашей программы положите в репозиторий файлы и папки с соответствующими именами. Файлы должны быть пустыми, если не указано обратного.

Получение списка файлов в каталоге и подкаталогах в Python

Чтобы получить список всех файлов в папке или каталоге и его подпапках или подкаталогах в Python, мы будем использовать функцию os.walk(), которая создает итератор по текущему каталогу, его подпапкам и файлам.

В этом руководстве мы рассмотрим некоторые примеры, демонстрирующие, как получить список всех файлов в каталоге и его подкаталогах.

Пример 1

В этом примере мы возьмем путь к каталогу и попытаемся рекурсивно перечислить все файлы в каталоге и его подкаталогах.

В приведенной выше программе мы использовали вложенный For Loop.

Пример 2: с определенным расширением

В этом примере мы возьмем путь к каталогу и попытаемся рекурсивно перечислить все файлы с определенным расширением .py в этом каталоге и его подкаталогах.

В этом руководстве мы узнали получения списка всех файлов в каталоге и его подкаталогах.

Listing of all files in directory?

Can anybody help me create a function which will create a list of all files under a certain directory by using pathlib library?

I expected to have a single list which would have the paths above, but my code returns a nested list.

Here is my code:

Hope anybody could correct me.

martineau's user avatar

12 Answers 12

Use Path.glob() to list all files and directories. And then filter it in a List Comprehensions.

More from the pathlib module:

    , part of the standard library.

Trenton McKinney's user avatar

prasastoadi's user avatar

With pathlib, it is as simple as the below comand.

Aditya Bhatt's user avatar

If you can assume that only file objects have a . in the name (i.e., .txt, .png, etc.) you can do a glob or recursive glob search.

But that’s not always the case. Sometimes there are hidden directories like .ipynb_checkpoints and files that do not have extensions. In that case, use list comprehension or a filter to sort out the Path objects that are files.

blaylockbk's user avatar

A similar, more functional-oriented solution to @prasastoadi’s one can be achieved by using the built-in filter function of Python:

If your files have the same suffix, like .txt , you can use rglob to list the main directory and all subdirectories, recursively.

If you need to apply any useful Path function to each path. For example, accessing the name property:

Where INPUT_PATH is the path to your main directory, and Path is imported from pathlib .

How do I list all files of a directory?

How can I list all files of a directory in Python and add them to a list ?

21 Answers 21

os.listdir() returns everything inside a directory — including both files and directories.

os.path ‘s isfile() can be used to only list files:

Alternatively, os.walk() yields two lists for each directory it visits — one for files and one for dirs. If you only want the top directory you can break the first time it yields:

Armen Michaeli's user avatar

I prefer using the glob module, as it does pattern matching and expansion.

It does pattern matching intuitively

It will return a list with the queried files and directories:

Note that glob ignores files and directories that begin with a dot . , as those are considered hidden files and directories, unless the pattern is something like .* .

Use glob.escape to escape strings that are not meant to be patterns:

list in the current directory

With listdir in os module you get the files and the folders in the current dir

Looking in a directory

with glob you can specify a type of file to list like this

get the full path of only files in the current directory

Getting the full path name with os.path.abspath

You get the full path in return

Walk: going through sub directories

os.walk returns the root, the directories list and the files list, that is why I unpacked them in r, d, f in the for loop; it, then, looks for other files and directories in the subfolders of the root and so on until there are no subfolders.

To go up in the directory tree

Get files of a particular subdirectory with os.listdir()

os.walk(‘.’) — current directory

next(os.walk(‘.’)) and os.path.join(‘dir’, ‘file’)

os.listdir() — get only txt files

Using glob to get the full path of the files

Using os.path.isfile to avoid directories in the list

Using pathlib from Python 3.4

With list comprehension :

Use glob method in pathlib.Path()

Get all and only files with os.walk: checks only in the third element returned, i.e. the list of the files

Get only files with next in a directory: returns only the file in the root folder

Get only directories with next and walk in a directory, because in the [1] element there are the folders only

Get all the subdir names with walk

os.scandir() from Python 3.5 and greater

PythonProgrammi's user avatar

will return a list of all files and directories in «somedirectory».

A one-line solution to get only list of files (no subdirectories):

or absolute pathnames:

Getting Full File Paths From a Directory and All Its Subdirectories

    The path I provided in the above function contained 3 files— two of them in the root directory, and another in a subfolder called «SUBFOLDER.» You can now do things like:

print full_file_paths which will print the list:

  • [‘/Users/johnny/Desktop/TEST/file1.txt’, ‘/Users/johnny/Desktop/TEST/file2.txt’, ‘/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat’]

If you’d like, you can open and read the contents, or focus only on files with the extension «.dat» like in the code below:

Читать:
Html как сделать чтобы текст не переносился на следующую строку

Since version 3.4 there are builtin iterators for this which are a lot more efficient than os.listdir() :

According to PEP 428, the aim of the pathlib library is to provide a simple hierarchy of classes to handle filesystem paths and the common operations users do over them.

Note that os.walk() uses os.scandir() instead of os.listdir() from version 3.5, and its speed got increased by 2-20 times according to PEP 471.

Let me also recommend reading ShadowRanger’s comment below.

Peter Mortensen's user avatar

Preliminary notes

Although there’s a clear differentiation between file and directory terms in the question text, some may argue that directories are actually special files

The statement: "all files of a directory" can be interpreted in two ways:

All direct (or level 1) descendants only

All descendants in the whole directory tree (including the ones in sub-directories)

When the question was asked, I imagine that Python 2, was the LTS version, however the code samples will be run by Python 3(.5) (I’ll keep them as Python 2 compliant as possible; also, any code belonging to Python that I’m going to post, is from v3.5.4 — unless otherwise specified).
That has consequences related to another keyword in the question: "add them into a list":

In pre Python 2.2 versions, sequences (iterables) were mostly represented by lists (tuples, sets, . )

In Python 2.2, the concept of generator ([Python.Wiki]: Generators) — courtesy of [Python.Docs]: Simple statements — The yield statement) — was introduced. As time passed, generator counterparts started to appear for functions that returned / worked with lists

In Python 3, generator is the default behavior

Not sure if returning a list is still mandatory (or a generator would do as well), but passing a generator to the list constructor, will create a list out of it (and also consume it). The example below illustrates the differences on [Python.Docs]: Built-in functions — map(function, iterable, *iterables)

The examples will be based on a directory called root_dir with the following structure (this example is for Win, but I’m using the same tree on Nix as well). Note that I’ll be reusing the console:

Solutions

Programmatic approaches

1. [Python.Docs]: os.listdir(path=’.’)

Return a list containing the names of the entries in the directory given by path. The list is in arbitrary order, and does not include the special entries ‘.’ and ‘..’ .

A more elaborate example (code_os_listdir.py):

Notes:

There are two implementations:

One that uses generators (of course here it seems useless, since I immediately convert the result to a list)

The classic one (function names ending in _old)

Recursion is used (to get into subdirectories)

For each implementation there are two functions:

One that starts with an underscore (_): "private" (should not be called directly) — that does all the work

The public one (wrapper over previous): it just strips off the initial path (if required) from the returned entries. It’s an ugly implementation, but it’s the only idea that I could come with at this point

In terms of performance, generators are generally a little bit faster (considering both creation and iteration times), but I didn’t test them in recursive functions, and also I am iterating inside the function over inner generators — don’t know how performance friendly is that

Play with the arguments to get different results

Output:

2. [Python.Docs]: os.scandir(path=’.’)

In Python 3.5+ only, backport: [PyPI]: scandir:

Return an iterator of os.DirEntry objects corresponding to the entries in the directory given by path. The entries are yielded in arbitrary order, and the special entries ‘.’ and ‘..’ are not included.

Using scandir() instead of listdir() can significantly increase the performance of code that also needs file type or file attribute information, because os.DirEntry objects expose this information if the operating system provides it when scanning a directory. All os.DirEntry methods may perform a system call, but is_dir() and is_file() usually only require a system call for symbolic links; os.DirEntry.stat() always requires a system call on Unix but only requires one for symbolic links on Windows.

Notes:

Similar to os.listdir

But it’s also more flexible (and offers more functionality), more Pythonic (and in some cases, faster)

3. [Python.Docs]: os.walk(top, topdown=True, onerror=None, followlinks=False)

Generate the file names in a directory tree by walking the tree either top-down or bottom-up. For each directory in the tree rooted at directory top (including top itself), it yields a 3-tuple ( dirpath , dirnames , filenames ).

Notes:

Under the scenes, it uses os.scandir (os.listdir on older (Python) versions)

It does the heavy lifting by recurring in subfolders

4. [Python.Docs]: glob.glob(pathname, *, root_dir=None, dir_fd=None, recursive=False, include_hidden=False)

Or glob.iglob:

Return a possibly-empty list of path names that match pathname, which must be a string containing a path specification. pathname can be either absolute (like /usr/src/Python-1.5/Makefile ) or relative (like ../../Tools/*/*.gif ), and can contain shell-style wildcards. Broken symlinks are included in the results (as in the shell).
.
Changed in version 3.5: Support for recursive globs using “ ** ”.

Notes:

For large trees (especially if recursive is on), iglob is preferred

Allows advanced filtering based on name (due to the wildcard)

5. [Python.Docs]: class pathlib.Path(*pathsegments)

Notes:

This is one way of achieving our goal

It’s the OOP style of handling paths

Offers lots of functionalities

6. [Python 2.Docs]: dircache.listdir(path)

Python 2 only

But, according to [GitHub]: python/cpython — (2.7) cpython/Lib/dircache.py, it’s just a (thin) wrapper over os.listdir with caching

7. Native OS APIs

ctypes is a foreign function library for Python. It provides C compatible data types, and allows calling functions in DLLs or shared libraries. It can be used to wrap these libraries in pure Python.

Notes:

It loads the three functions from LibC (libc.so — loaded in the current process) and calls them (for more details check [SO]: How do I check whether a file exists without exceptions? (@CristiFati’s answer) — last notes from item #4.). That would place this approach very close to the Python / C edge

NixDirent64 is the CTypes representation of struct dirent64 from [Man7]: dirent.h(0P) (so are the DT_ constants) from my Ubuntu OS. On other flavors / versions, the structure definition might differ, and if so, the CTypes alias should be updated, otherwise it will yield Undefined Behavior

It returns data in the os.walk‘s format. I didn’t bother to make it recursive, but starting from the existing code, that would be a fairly trivial task

Everything is doable on Win as well, the data (libraries, functions, structs, constants, . ) differ

Output:

8. [TimGolden]: win32file.FindFilesW

Retrieves a list of matching filenames, using the Windows Unicode API. An interface to the API FindFirstFileW/FindNextFileW/Find close functions.

Notes:

  • win32file.FindFilesW is part of [GitHub]: mhammond/pywin32 — Python for Windows (pywin32) Extensions, which is a Python wrapper over WinAPIs
9. Use some (other) 3 rd -party package that does the trick

Most likely, will rely on one (or more) of the above (maybe with slight customizations).

Notes:

Code is meant to be portable (except places that target a specific area — which are marked) or cross:

Python version (2, 3, )

Multiple path styles (absolute, relatives) were used across the above variants, to illustrate the fact that the "tools" used are flexible in this direction

_get_dir_content (from point #1.) can be implemented using any of these approaches (some will require more work and some less)

  • Some advanced filtering (instead of just file vs.dir) could be done: e.g. the include_folders argument could be replaced by another one (e.g. filter_func) which would be a function that takes a path as an argument: filter_func=lambda x: True (this doesn’t strip out anything) and inside _get_dir_content something like: if not filter_func(entry_with_path): continue (if the function fails for one entry, it will be skipped), but the more complex the code becomes, the longer it will take to execute

Nota Bene! Since recursion is used, I must mention that I did some tests on my laptop (Win 10 pc064), totally unrelated to this problem, and when the recursion level was reaching values somewhere in the (990 .. 1000) range (recursionlimit — 1000 (default)), I got StackOverflow :). If the directory tree exceeds that limit (I am not an FS expert, so I don’t know if that is even possible), that could be a problem.
I must also mention that I didn’t try to increase recursionlimit, but in theory there will always be the possibility for failure, if the dir depth is larger than the highest possible recursionlimit (on that machine).
Check [SO]: _csv.Error: field larger than field limit (131072) (@CristiFati’s answer) for more details on the topic

Code samples are for demonstrative purposes only. That means that I didn’t take into account error handling (I don’t think there’s any try / except / else / finally block), so the code is not robust (the reason is: to keep it as simple and short as possible). For production, error handling should be added as well

Other approaches:

1. Use Python only as a wrapper

Everything is done using another technology

That technology is invoked from Python

The most famous flavor that I know is what I call the SysAdmin approach:

Use Python (or any programming language for that matter) in order to execute Shell commands (and parse their outputs)

Some consider this a neat hack

I consider it more like a lame workaround (gainarie), as the action per se is performed from Shell (Cmd in this case), and thus doesn’t have anything to do with Python

Filtering (grep / findstr) or output formatting could be done on both sides, but I’m not going to insist on it. Also, I deliberately used os.system instead of [Python.Docs]: subprocess — Subprocess management routines (run, check_output, . )

In general, this approach is to be avoided, since if some command output format slightly differs between OS versions / flavors, the parsing code should be adapted as well — not to mention differences between locales.

Похожие статьи