Как я могу перечислить все файлы каталога в Python и добавить их в list
?
Как мне вывести список всех файлов каталога?
Ответы (21)
Один мудрый учитель сказал мне однажды, что:
Когда существует несколько устоявшихся способов сделать что-либо, ни один из них не подходит для всех случаев.
Таким образом, я добавлю решение для подмножества проблемы: довольно часто мы хотим только проверить, соответствует ли файл начальной и конечной строкам, не заходя в подкаталоги. Таким образом, нам нужна функция, которая возвращает список имен файлов, например:
filenames = dir_filter('foo/baz', radical='radical', extension='.txt')
Если вы хотите сначала объявить две функции, это можно сделать:
def file_filter(filename, radical='', extension=''):
"Check if a filename matches a radical and extension"
if not filename:
return False
filename = filename.strip()
return(filename.startswith(radical) and filename.endswith(extension))
def dir_filter(dirname='', radical='', extension=''):
"Filter filenames in directory according to radical and extension"
if not dirname:
dirname = '.'
return [filename for filename in os.listdir(dirname)
if file_filter(filename, radical, extension)]
Это решение можно легко обобщить с помощью регулярных выражений (и вы можете добавить аргумент pattern
, если вы не хотите, чтобы ваши шаблоны всегда придерживались начала или конца имени файла).
Для лучших результатов вы можете использовать метод listdir()
модуля os
вместе с генератором (генератор - это мощный итератор, который сохраняет свое состояние, помните?). Следующий код отлично работает с обеими версиями: Python 2 и Python 3.
Вот код:
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)
Метод listdir()
возвращает список записей для данного каталога. Метод os.path.isfile()
возвращает True
, если данная запись является файлом. И оператор yield
завершает выполнение функции, но сохраняет ее текущее состояние и возвращает только имя записи, обнаруженной как файл. Все вышесказанное позволяет нам перебрать функцию генератора.
Для Python 2:
pip install rglob
Затем выполните
import rglob
file_list = rglob.rglob("/home/base/dir/", "*")
print file_list
Когда можно избежать внешнего депривации, сделайте это. В чем добавленная стоимость использования внешней зависимости, когда все, что вам нужно, уже есть в языке?
import os
import os.path
def get_files(target_dir):
item_list = os.listdir(target_dir)
file_list = list()
for item in item_list:
item_dir = os.path.join(target_dir,item)
if os.path.isdir(item_dir):
file_list += get_files(item_dir)
else:
file_list.append(item_dir)
return file_list
Здесь я использую рекурсивную структуру.
То же самое может быть достигнуто только в одной строке с pathlib
: filter(Path.is_file, Path().rglob('*'))
Другой очень удобочитаемый вариант для Python 3.4+ - использование pathlib.Path.glob:
from pathlib import Path
folder = '/foo'
[f for f in Path(folder).glob('*') if f.is_file()]
Это просто сделать более конкретным, например ищите только исходные файлы Python, которые не являются символическими ссылками, также во всех подкаталогах:
[f for f in Path(folder).glob('**/*.py') if not f.is_symlink()]
Предварительные примечания
- Хотя в тексте вопроса существует четкое различие между терминами файл и каталог , некоторые могут утверждать, что каталоги на самом деле являются специальными файлами
- Утверждение: « все файлы каталога » можно интерпретировать двумя способами:
- Все прямые (или уровень 1) потомки только
- Все потомки во всем дереве каталогов (в том числе в подкаталогах)
-
Когда был задан вопрос, я предполагал, что Python 2 , был версией LTS , однако образцы кода 954339494 будут запускаться <4211> 3 ( .5 ) (Я сохраню их как Python 2 совместимыми, насколько это возможно; также, любой код, принадлежащий >, которое я собираюсь опубликовать, взято из v3.5.4 - если не указано иное). Это имеет последствия, связанные с другим ключевым словом в вопросе: « добавить их в список »:
- В версиях до Python 2.2 до , последовательности (итерации) в основном представлялись списками (кортежи, наборы, ...)
- В Python 2.2 используется концепция генератора ([Python.Wiki]: Генераторы) - любезно предоставлено [Python] 350119 yield statement ) - был введен. По прошествии времени аналоги генератора стали появляться для функций, которые возвращали / работали со списками
- В Python 3 генератор является поведением по умолчанию
- Не уверен, что возврат списка по-прежнему является обязательным (или генератор тоже подойдет), но передача генератора в конструктор list создаст список из него (а также потребляет его) . В приведенном ниже примере показаны различия в [Python 3]: map ( функция, итерация, ... )
>>> import sys >>> sys.version '2.7.10 (default, Mar 8 2016, 15:02:46) [MSC v.1600 64 bit (AMD64)]' >>> m = map(lambda x: x, [1, 2, 3]) # Just a dummy lambda function >>> m, type(m) ([1, 2, 3], <type 'list'>) >>> len(m) 3
>>> import sys >>> sys.version '3.5.4 (v3.5.4:3f56838, Aug 8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)]' >>> m = map(lambda x: x, [1, 2, 3]) >>> m, type(m) (<map object at 0x000001B4257342B0> <class 'map'>) >>> len(m) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: object of type 'map' has no len() >>> lm0 = list(m) # Build a list from the generator >>> lm0, type(lm0) ([1, 2, 3], <class 'list'>) >>> >>> lm1 = list(m) # Build a list from the same generator >>> lm1, type(lm1) # Empty list now - generator already consumed ([], <class 'list'>)
-
Примеры будут основаны на каталоге с именем root_dir со следующей структурой (этот пример для Win , но я использую то же дерево на Lnx также):
E:\Work\Dev\StackOverflow\q003207219>tree /f "root_dir" Folder PATH listing for volume Work Volume serial number is 00000029 3655:6FED E:\WORK\DEV\STACKOVERFLOW\Q003207219\ROOT_DIR ¦ file0 ¦ file1 ¦ +---dir0 ¦ +---dir00 ¦ ¦ ¦ file000 ¦ ¦ ¦ ¦ ¦ +---dir000 ¦ ¦ file0000 ¦ ¦ ¦ +---dir01 ¦ ¦ file010 ¦ ¦ file011 ¦ ¦ ¦ +---dir02 ¦ +---dir020 ¦ +---dir0200 +---dir1 ¦ file10 ¦ file11 ¦ file12 ¦ +---dir2 ¦ ¦ file20 ¦ ¦ ¦ +---dir20 ¦ file200 ¦ +---dir3
Решения
Программные подходы:
-
[Python 3]: os. listdir ( path = '.' )
Вернуть список, содержащий имена записей в каталоге, заданном путем. Список составлен в произвольном порядке и не включает специальные записи
'.'
и'..'
...
>>> import os >>> root_dir = "root_dir" # Path relative to current dir (os.getcwd()) >>> >>> os.listdir(root_dir) # List all the items in root_dir ['dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1'] >>> >>> [item for item in os.listdir(root_dir) if os.path.isfile(os.path.join(root_dir, item))] # Filter items and only keep files (strip out directories) ['file0', 'file1']
Более сложный пример ( code_os_listdir.py ):
import os from pprint import pformat def _get_dir_content(path, include_folders, recursive): entries = os.listdir(path) for entry in entries: entry_with_path = os.path.join(path, entry) if os.path.isdir(entry_with_path): if include_folders: yield entry_with_path if recursive: for sub_entry in _get_dir_content(entry_with_path, include_folders, recursive): yield sub_entry else: yield entry_with_path def get_dir_content(path, include_folders=True, recursive=True, prepend_folder_name=True): path_len = len(path) + len(os.path.sep) for item in _get_dir_content(path, include_folders, recursive): yield item if prepend_folder_name else item[path_len:] def _get_dir_content_old(path, include_folders, recursive): entries = os.listdir(path) ret = list() for entry in entries: entry_with_path = os.path.join(path, entry) if os.path.isdir(entry_with_path): if include_folders: ret.append(entry_with_path) if recursive: ret.extend(_get_dir_content_old(entry_with_path, include_folders, recursive)) else: ret.append(entry_with_path) return ret def get_dir_content_old(path, include_folders=True, recursive=True, prepend_folder_name=True): path_len = len(path) + len(os.path.sep) return [item if prepend_folder_name else item[path_len:] for item in _get_dir_content_old(path, include_folders, recursive)] def main(): root_dir = "root_dir" ret0 = get_dir_content(root_dir, include_folders=True, recursive=True, prepend_folder_name=True) lret0 = list(ret0) print(ret0, len(lret0), pformat(lret0)) ret1 = get_dir_content_old(root_dir, include_folders=False, recursive=True, prepend_folder_name=False) print(len(ret1), pformat(ret1)) if __name__ == "__main__": main()
Примечания :
- Есть две реализации:
- Тот, который использует генераторы (конечно, здесь это кажется бесполезным, так как я сразу конвертирую результат в список)
- Классический (имена функций заканчиваются на _old )
- Используется рекурсия (чтобы попасть в подкаталоги)
- Для каждой реализации есть две функции:
- Тот, который начинается с подчеркивания ( _ ): "частный" (не следует вызывать напрямую) - это делает всю работу
- Публичный (обертка поверх предыдущего): он просто удаляет исходный путь (если требуется) из возвращаемых записей. Это уродливая реализация, но это единственная идея, которую я мог придумать на данный момент
- С точки зрения производительности генераторы обычно немного быстрее (учитывая как создание , так и итерацию раз), но я не тестировал их в рекурсивных функциях, а также я я повторяю внутри функции над внутренними генераторами - не знаю, насколько удобна производительность, что
- Поиграйте с аргументами, чтобы получить разные результаты
Вывод :
(py35x64_test) E:\Work\Dev\StackOverflow\q003207219>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" "code_os_listdir.py" <generator object get_dir_content at 0x000001BDDBB3DF10> 22 ['root_dir\\dir0', 'root_dir\\dir0\\dir00', 'root_dir\\dir0\\dir00\\dir000', 'root_dir\\dir0\\dir00\\dir000\\file0000', 'root_dir\\dir0\\dir00\\file000', 'root_dir\\dir0\\dir01', 'root_dir\\dir0\\dir01\\file010', 'root_dir\\dir0\\dir01\\file011', 'root_dir\\dir0\\dir02', 'root_dir\\dir0\\dir02\\dir020', 'root_dir\\dir0\\dir02\\dir020\\dir0200', 'root_dir\\dir1', 'root_dir\\dir1\\file10', 'root_dir\\dir1\\file11', 'root_dir\\dir1\\file12', 'root_dir\\dir2', 'root_dir\\dir2\\dir20', 'root_dir\\dir2\\dir20\\file200', 'root_dir\\dir2\\file20', 'root_dir\\dir3', 'root_dir\\file0', 'root_dir\\file1'] 11 ['dir0\\dir00\\dir000\\file0000', 'dir0\\dir00\\file000', 'dir0\\dir01\\file010', 'dir0\\dir01\\file011', 'dir1\\file10', 'dir1\\file11', 'dir1\\file12', 'dir2\\dir20\\file200', 'dir2\\file20', 'file0', 'file1']
- Есть две реализации:
-
[Python 3]: os. scandir ( path = '.' ) () () (<4211334339639> Python <4211952195 > +, backport: [PyPI]: scandir)
Вернуть итератор объектов os.DirEntry, соответствующих записям в каталоге, заданном путем . Записи выводятся в произвольном порядке, а специальные записи
'.'
и'..'
не включаются.Использование scandir () вместо listdir () может значительно повысить производительность кода, которому также нужна информация о типе файла или атрибуте файла, поскольку <4291195Entry > объекты предоставляют эту информацию, если операционная система предоставляет ее при сканировании каталога. Все методы os.DirEntry могут выполнять системный вызов, но is_dir () и is_file () обычно требуют системного вызова только для символьных ссылок; os.DirEntry.stat () всегда требует системного вызова в Unix, но требует только одного для символьных ссылок в Windows.
>>> import os >>> root_dir = os.path.join(".", "root_dir") # Explicitly prepending current directory >>> root_dir '.\\root_dir' >>> >>> scandir_iterator = os.scandir(root_dir) >>> scandir_iterator <nt.ScandirIterator object at 0x00000268CF4BC140> >>> [item.path for item in scandir_iterator] ['.\\root_dir\\dir0', '.\\root_dir\\dir1', '.\\root_dir\\dir2', '.\\root_dir\\dir3', '.\\root_dir\\file0', '.\\root_dir\\file1'] >>> >>> [item.path for item in scandir_iterator] # Will yield an empty list as it was consumed by previous iteration (automatically performed by the list comprehension) [] >>> >>> scandir_iterator = os.scandir(root_dir) # Reinitialize the generator >>> for item in scandir_iterator : ... if os.path.isfile(item.path): ... print(item.name) ... file0 file1
Примечания :
- Это похоже на
os.listdir
- Но он также более гибкий (и предлагает больше функций), больше Python ic (и в некоторых случаях быстрее)
- Это похоже на
-
[Python 3]: glob. glob ( путь, *, рекурсивный = False ) ([]. Glob > iglob ( путь, *, рекурсивный = False ))
Вернуть, возможно, пустой список имен путей, соответствующих имени пути , который должен быть строкой, содержащей спецификацию пути. путь может быть абсолютным (например,
/usr/src/Python-1.5/Makefile
) или относительным (например,../../Tools/*/*.gif
) и может содержать подстановочные знаки в стиле оболочки. Неработающие символические ссылки включаются в результаты (как и в оболочке).
...
Изменено в версии 3.5 : Поддержка рекурсивных глобусов с использованием «<4294> »11954 .
>>> import glob, os >>> wildcard_pattern = "*" >>> root_dir = os.path.join("root_dir", wildcard_pattern) # Match every file/dir name >>> root_dir 'root_dir\\*' >>> >>> glob_list = glob.glob(root_dir) >>> glob_list ['root_dir\\dir0', 'root_dir\\dir1', 'root_dir\\dir2', 'root_dir\\dir3', 'root_dir\\file0', 'root_dir\\file1'] >>> >>> [item.replace("root_dir" + os.path.sep, "") for item in glob_list] # Strip the dir name and the path separator from begining ['dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1'] >>> >>> for entry in glob.iglob(root_dir + "*", recursive=True): ... print(entry) ... root_dir\ root_dir\dir0 root_dir\dir0\dir00 root_dir\dir0\dir00\dir000 root_dir\dir0\dir00\dir000\file0000 root_dir\dir0\dir00\file000 root_dir\dir0\dir01 root_dir\dir0\dir01\file010 root_dir\dir0\dir01\file011 root_dir\dir0\dir02 root_dir\dir0\dir02\dir020 root_dir\dir0\dir02\dir020\dir0200 root_dir\dir1 root_dir\dir1\file10 root_dir\dir1\file11 root_dir\dir1\file12 root_dir\dir2 root_dir\dir2\dir20 root_dir\dir2\dir20\file200 root_dir\dir2\file20 root_dir\dir3 root_dir\file0 root_dir\file1
Примечания :
- Использует
os.listdir
- Для больших деревьев (особенно если рекурсивный включен), iglob является предпочтительным
- Разрешает расширенную фильтрацию по имени (из-за подстановочного знака)
- Использует
-
[Python 3]: class pathlib. Путь ( * pathsegments ) () () ( Python <421195426349843211954> + Python <4211954> , backport: [PyPI]: pathlib2)
>>> import pathlib >>> root_dir = "root_dir" >>> root_dir_instance = pathlib.Path(root_dir) >>> root_dir_instance WindowsPath('root_dir') >>> root_dir_instance.name 'root_dir' >>> root_dir_instance.is_dir() True >>> >>> [item.name for item in root_dir_instance.glob("*")] # Wildcard searching for all direct descendants ['dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1'] >>> >>> [os.path.join(item.parent.name, item.name) for item in root_dir_instance.glob("*") if not item.is_dir()] # Display paths (including parent) for files only ['root_dir\\file0', 'root_dir\\file1']
Примечания :
- Это один способ достижения нашей цели
- Это стиль ООП обработки путей
- Предлагает множество функций
-
[Python 2]: dircache.listdir (path) ( Python 2 только)
- Но, согласно [GitHub]: python / cpython - (2.7) cpython / Lib / dircache.py, это просто (тонкая) оболочка над
os.listdir
с кешированием
def listdir(path): """List directory contents, using cache.""" try: cached_mtime, list = cache[path] del cache[path] except KeyError: cached_mtime, list = -1, [] mtime = os.stat(path).st_mtime if mtime != cached_mtime: list = os.listdir(path) list.sort() cache[path] = mtime, list return list
- Но, согласно [GitHub]: python / cpython - (2.7) cpython / Lib / dircache.py, это просто (тонкая) оболочка над
-
[man7]: OPENDIR (3) / [man7]: READDIR (3) / [man7]: CLOSEDIR (3) <4211339856> [man7]: CLOSEDIR (3) <421133984 > [Python 3]: ctypes - библиотека внешних функций для Python ( POSIX специфическая)
ctypes - это библиотека внешних функций для Python. Он предоставляет типы данных, совместимые с C, и позволяет вызывать функции в библиотеках DLL или совместно используемых библиотеках. Его можно использовать для обертывания этих библиотек на чистом Python.
code_ctypes.py :
#!/usr/bin/env python3 import sys from ctypes import Structure, \ c_ulonglong, c_longlong, c_ushort, c_ubyte, c_char, c_int, \ CDLL, POINTER, \ create_string_buffer, get_errno, set_errno, cast DT_DIR = 4 DT_REG = 8 char256 = c_char * 256 class LinuxDirent64(Structure): _fields_ = [ ("d_ino", c_ulonglong), ("d_off", c_longlong), ("d_reclen", c_ushort), ("d_type", c_ubyte), ("d_name", char256), ] LinuxDirent64Ptr = POINTER(LinuxDirent64) libc_dll = this_process = CDLL(None, use_errno=True) # ALWAYS set argtypes and restype for functions, otherwise it's UB!!! opendir = libc_dll.opendir readdir = libc_dll.readdir closedir = libc_dll.closedir def get_dir_content(path): ret = [path, list(), list()] dir_stream = opendir(create_string_buffer(path.encode())) if (dir_stream == 0): print("opendir returned NULL (errno: {:d})".format(get_errno())) return ret set_errno(0) dirent_addr = readdir(dir_stream) while dirent_addr: dirent_ptr = cast(dirent_addr, LinuxDirent64Ptr) dirent = dirent_ptr.contents name = dirent.d_name.decode() if dirent.d_type & DT_DIR: if name not in (".", ".."): ret[1].append(name) elif dirent.d_type & DT_REG: ret[2].append(name) dirent_addr = readdir(dir_stream) if get_errno(): print("readdir returned NULL (errno: {:d})".format(get_errno())) closedir(dir_stream) return ret def main(): print("{:s} on {:s}\n".format(sys.version, sys.platform)) root_dir = "root_dir" entries = get_dir_content(root_dir) print(entries) if __name__ == "__main__": main()
Примечания :
- Он загружает три функции из libc (загружается в текущем процессе) и вызывает их (подробнее см. [SO]: Как проверить, существует ли файл без исключений? ( @ CristiFati ответ) - последние примечания из пункта # 4. ). Это поместило бы этот подход очень близко к Python / C краю
- LinuxDirent64 - это ctypes представление struct dirent64 из [man7]: dirent.h (0P) <99004211> DT_ константы) с моей машины: Ubtu 16 x64 ( 4.10.0-40-generic и libc6-dev: amd433990) .42118 В других вариантах / версиях определение структуры может отличаться, и если это так, необходимо обновить псевдоним ctypes , в противном случае будет получено Неопределенное поведение
- Он возвращает данные в формате
os.walk
. Я не стал делать это рекурсивным, но, исходя из существующего кода, это было бы довольно тривиальной задачей - Все возможно и на Win , данные (библиотеки, функции, структуры, константы, ...) отличаются
Вывод :
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q003207219]> ./code_ctypes.py 3.5.2 (default, Nov 12 2018, 13:43:14) [GCC 5.4.0 20160609] on linux ['root_dir', ['dir2', 'dir1', 'dir3', 'dir0'], ['file1', 'file0']]
-
[ActiveState.Docs]: win32file.FindFilesW ( Win специфичный)
Получает список совпадающих имен файлов, используя Windows Unicode API. Интерфейс к функциям API FindFirstFileW / FindNextFileW / Find close.
>>> import os, win32file, win32con >>> root_dir = "root_dir" >>> wildcard = "*" >>> root_dir_wildcard = os.path.join(root_dir, wildcard) >>> entry_list = win32file.FindFilesW(root_dir_wildcard) >>> len(entry_list) # Don't display the whole content as it's too long 8 >>> [entry[-2] for entry in entry_list] # Only display the entry names ['.', '..', 'dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1'] >>> >>> [entry[-2] for entry in entry_list if entry[0] & win32con.FILE_ATTRIBUTE_DIRECTORY and entry[-2] not in (".", "..")] # Filter entries and only display dir names (except self and parent) ['dir0', 'dir1', 'dir2', 'dir3'] >>> >>> [os.path.join(root_dir, entry[-2]) for entry in entry_list if entry[0] & (win32con.FILE_ATTRIBUTE_NORMAL | win32con.FILE_ATTRIBUTE_ARCHIVE)] # Only display file "full" names ['root_dir\\file0', 'root_dir\\file1']
Примечания :
-
win32file.FindFilesW
является частью [GitHub]: mhammond / pywin32 - Python для Windows (pywin32) Extensions, который является Python оболочкой 42631199 WINAPI. >- Ссылка на документацию взята из ActiveState, так как я не нашел никакой PyWin32 официальной документации
-
- Установите какой-нибудь (другой) сторонний пакет, который поможет
- Скорее всего, будет полагаться на одно (или несколько) из вышеперечисленных (возможно, с небольшими изменениями)
Примечания :
-
Код должен быть переносимым (за исключением мест, нацеленных на определенную область - которые отмечены) или крестиком:
- платформа ( Nix , Win ,)
- Python версия (2, 3,)
-
В приведенных выше вариантах использовалось несколько стилей пути (абсолютные, родственники), чтобы проиллюстрировать тот факт, что используемые «инструменты» гибки в этом направлении
-
os.listdir
иos.scandir
используйте opendir / readdir / <95004: функция поиска <95004: закрытая > / [MS.Docs]: функция FindNextFileW / [MS.Docs]: функция FindClose) (через [GitHub]: python / cpython) /Modules/posixmodule.c) -
win32file.FindFilesW
также использует эти ( Win специфические) функции (через [GitHub]: mhammond / pywin32 - (master) pywin32 / win32 / srile.c />) -
_get_dir_content (из пункта # 1. ) можно реализовать с использованием любого из этих подходов (для некоторых потребуется больше работы, а для некоторых - меньше)
- Можно выполнить некоторую расширенную фильтрацию (вместо простого файла по сравнению с каталогом): например, аргумент include_folders можно заменить другим (например, filter_func ), которая будет функцией, которая принимает путь в качестве аргумента:
filter_func=lambda x: True
(при этом ничего не удаляется) и внутри _get_dir_content что-то вроде:if not filter_func(entry_with_path): continue
(если функция не работает для одной записи, она будет пропущена), но чем сложнее становится код, тем больше времени потребуется для выполнения
- Можно выполнить некоторую расширенную фильтрацию (вместо простого файла по сравнению с каталогом): например, аргумент include_folders можно заменить другим (например, filter_func ), которая будет функцией, которая принимает путь в качестве аргумента:
-
Nota bene! Поскольку используется рекурсия, я должен упомянуть, что я провел несколько тестов на своем ноутбуке ( Win 10 x64 ), совершенно не связанных с этой проблемой, и когда уровень рекурсии достигал значений где-то в диапазоне (990 .. 1000) ( предел рекурсии - 1000 (по умолчанию)), я получил StackOverflow :). Если дерево каталогов превышает этот предел (я не эксперт по FS , поэтому я не знаю, возможно ли это вообще), это может быть проблемой.
Я должен также упомянуть, что я не пытался увеличить предел рекурсии , потому что у меня нет опыта в этой области (насколько я могу его увеличить, прежде чем мне также придется увеличивать стек на уровне ОС ), но теоретически всегда будет возможность сбоя, если глубина каталога больше максимально возможного ограничения рекурсии (на этой машине) -
Примеры кода предназначены только для демонстрационных целей. Это означает, что я не учел обработку ошибок (я не думаю, что есть try / кроме / <42119592> > else / наконец блок , поэтому код не является надежным (причина в том, чтобы он был как можно более простым и коротким). Для production также должна быть добавлена обработка ошибок
Другие подходы:
-
Используйте Python только в качестве оболочки
- Все сделано по другой технологии
- Эта технология вызывается из Python
-
Самая известная разновидность, которую я знаю, - это то, что я называю подходом системного администратора :
- Используйте Python (или любой другой язык программирования в этом отношении) для выполнения команд оболочки (и анализа их выходных данных)
- Некоторые считают это изящным взломом
- Я считаю это скорее неудачным решением ( gainarie ), поскольку действие само по себе выполняется из оболочки ( cmd и в данном случае) таким образом, не имеет ничего общего с Python .
- Фильтрация (
grep
/findstr
) или форматирование вывода могут выполняться с обеих сторон, но я не собираюсь на этом настаивать. Кроме того, я намеренно использовалos.system
вместоsubprocess.Popen
.
(py35x64_test) E:\Work\Dev\StackOverflow\q003207219>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" -c "import os;os.system(\"dir /b root_dir\")" dir0 dir1 dir2 dir3 file0 file1
Как правило, этого подхода следует избегать, поскольку, если формат вывода некоторых команд немного отличается между версиями / вариантами ОС , код синтаксического анализа также должен быть адаптирован; не говоря уже о различиях между регионами).
Я предоставлю образец одного лайнера, в котором исходный путь и тип файла могут быть предоставлены в качестве входных данных. Код возвращает список имен файлов с расширением csv. Используйте . на случай, если необходимо вернуть все файлы. Это также будет рекурсивно сканировать подкаталоги.
[y for x in os.walk(sourcePath) for y in glob(os.path.join(x[0], '*.csv'))]
При необходимости измените расширения файлов и исходный путь.
Если вы собираетесь использовать glob
, просто используйте glob('**/*.csv', recursive=True)
. Нет необходимости объединять это с os.walk()
для рекурсии (recursive
и **
поддерживаются начиная с Python 3.5).
Вот моя универсальная функция для этого. Он возвращает список путей к файлам, а не имен файлов, поскольку я обнаружил, что это более полезно. У него есть несколько необязательных аргументов, которые делают его универсальным. Например, я часто использую его с такими аргументами, как pattern='*.txt'
или subfolders=True
.
import os
import fnmatch
def list_paths(folder='.', pattern='*', case_sensitive=False, subfolders=False):
"""Return a list of the file paths matching the pattern in the specified
folder, optionally including files inside subfolders.
"""
match = fnmatch.fnmatchcase if case_sensitive else fnmatch.fnmatch
walked = os.walk(folder) if subfolders else [next(os.walk(folder))]
return [os.path.join(root, f)
for root, dirnames, filenames in walked
for f in filenames if match(f, pattern)]
os.listdir()
- список в текущем каталоге
С помощью listdir в модуле os вы получаете файлы и папки в текущем каталоге
import os
arr = os.listdir()
print(arr)
>>> ['$RECYCLE.BIN', 'work.txt', '3ebooks.txt', 'documents']
Поиск в каталоге
arr = os.listdir('c:\\files')
glob
из glob
с помощью glob вы можете указать тип файла для списка, например:
import glob
txtfiles = []
for file in glob.glob("*.txt"):
txtfiles.append(file)
glob
в понимании списка
mylist = [f for f in glob.glob("*.txt")]
получить полный путь только к файлам в текущем каталоге
import os
from os import listdir
from os.path import isfile, join
cwd = os.getcwd()
onlyfiles = [os.path.join(cwd, f) for f in os.listdir(cwd) if
os.path.isfile(os.path.join(cwd, f))]
print(onlyfiles)
['G:\\getfilesname\\getfilesname.py', 'G:\\getfilesname\\example.txt']
Получение полного имени пути с помощью
os.path.abspath
Вы получите взамен полный путь
import os
files_path = [os.path.abspath(x) for x in os.listdir()]
print(files_path)
['F:\\documenti\applications.txt', 'F:\\documenti\collections.txt']
Прогулка: просмотр подкаталогов
os.walk возвращает корень, список каталогов и список файлов, поэтому я распаковал их в r, d, f в цикле for; затем он ищет другие файлы и каталоги во вложенных папках корневого каталога и так далее, пока не останется вложенных папок.
import os
# Getting the current work directory (cwd)
thisdir = os.getcwd()
# r=root, d=directories, f = files
for r, d, f in os.walk(thisdir):
for file in f:
if file.endswith(".docx"):
print(os.path.join(r, file))
os.listdir()
: получить файлы в текущем каталоге (Python 2)
В Python 2, если вам нужен список файлов в текущем каталоге, вы должны указать аргумент как '.' или os.getcwd () в методе os.listdir.
import os
arr = os.listdir('.')
print(arr)
>>> ['$RECYCLE.BIN', 'work.txt', '3ebooks.txt', 'documents']
Для перехода вверх по дереву каталогов
# Method 1
x = os.listdir('..')
# Method 2
x= os.listdir('/')
Получить файлы:
os.listdir()
в определенном каталоге (Python 2 и 3)
import os
arr = os.listdir('F:\\python')
print(arr)
>>> ['$RECYCLE.BIN', 'work.txt', '3ebooks.txt', 'documents']
Получить файлы из определенного подкаталога с помощью
os.listdir()
import os
x = os.listdir("./content")
os.walk('.')
- текущий каталог
import os
arr = next(os.walk('.'))[2]
print(arr)
>>> ['5bs_Turismo1.pdf', '5bs_Turismo1.pptx', 'esperienza.txt']
next(os.walk('.'))
иos.path.join('dir', 'file')
import os
arr = []
for d,r,f in next(os.walk("F:\\_python")):
for file in f:
arr.append(os.path.join(r,file))
for f in arr:
print(files)
>>> F:\\_python\\dict_class.py
>>> F:\\_python\\programmi.txt
next(os.walk('F:\\')
- получить полный путь - понимание списка
[os.path.join(r,file) for r,d,f in next(os.walk("F:\\_python")) for file in f]
>>> ['F:\\_python\\dict_class.py', 'F:\\_python\\programmi.txt']
os.walk
- получить полный путь - все файлы в подкаталогах **
x = [os.path.join(r,file) for r,d,f in os.walk("F:\\_python") for file in f]
print(x)
>>> ['F:\\_python\\dict.py', 'F:\\_python\\progr.txt', 'F:\\_python\\readl.py']
os.listdir()
- получить только текстовые файлы
arr_txt = [x for x in os.listdir() if x.endswith(".txt")]
print(arr_txt)
>>> ['work.txt', '3ebooks.txt']
Использование
glob
для получения полного пути к файлам
Если мне нужен абсолютный путь к файлам:
from path import path
from glob import glob
x = [path(f).abspath() for f in glob("F:\\*.txt")]
for f in x:
print(f)
>>> F:\acquistionline.txt
>>> F:\acquisti_2018.txt
>>> F:\bootstrap_jquery_ecc.txt
Использование
os.path.isfile
для исключения каталогов в списке
import os.path
listOfFiles = [f for f in os.listdir() if os.path.isfile(f)]
print(listOfFiles)
>>> ['a simple game.py', 'data.txt', 'decorator.py']
Использование
pathlib
из Python 3.4
import pathlib
flist = []
for p in pathlib.Path('.').iterdir():
if p.is_file():
print(p)
flist.append(p)
>>> error.PNG
>>> exemaker.bat
>>> guiprova.mp3
>>> setup.py
>>> speak_gui2.py
>>> thumb.PNG
С list comprehension
:
flist = [p for p in pathlib.Path('.').iterdir() if p.is_file()]
В качестве альтернативы используйте pathlib.Path()
вместо pathlib.Path(".")
Использовать метод glob в pathlib.Path ()
import pathlib
py = pathlib.Path().glob("*.py")
for file in py:
print(file)
>>> stack_overflow_list.py
>>> stack_overflow_list_tkinter.py
Получить все и только файлы с помощью os.walk
import os
x = [i[2] for i in os.walk('.')]
y=[]
for t in x:
for f in t:
y.append(f)
print(y)
>>> ['append_to_list.py', 'data.txt', 'data1.txt', 'data2.txt', 'data_180617', 'os_walk.py', 'READ2.py', 'read_data.py', 'somma_defaltdic.py', 'substitute_words.py', 'sum_data.py', 'data.txt', 'data1.txt', 'data_180617']
Получить только файлы со следующим и перейти в каталог
import os
x = next(os.walk('F://python'))[2]
print(x)
>>> ['calculator.bat','calculator.py']
Получить только каталоги со следующим и перейти в каталог
import os
next(os.walk('F://python'))[1] # for the current dir use ('.')
>>> ['python3','others']
Получить все имена подкаталогов с помощью
walk
for r,d,f in os.walk("F:\\_python"):
for dirs in d:
print(dirs)
>>> .vscode
>>> pyexcel
>>> pyschool.py
>>> subtitles
>>> _metaprogramming
>>> .ipynb_checkpoints
os.scandir()
из Python 3.5 и выше
import os
x = [f.name for f in os.scandir() if f.is_file()]
print(x)
>>> ['calculator.bat','calculator.py']
# Another example with scandir (a little variation from docs.python.org)
# This one is more efficient than os.listdir.
# In this case, it shows the files only in the current directory
# where the script is executed.
import os
with os.scandir() as i:
for entry in i:
if entry.is_file():
print(entry.name)
>>> ebookmaker.py
>>> error.PNG
>>> exemaker.bat
>>> guiprova.mp3
>>> setup.py
>>> speakgui4.py
>>> speak_gui2.py
>>> speak_gui3.py
>>> thumb.PNG
Примеры:
Пример. 1: Сколько файлов в подкаталогах?
В этом примере мы ищем количество файлов, которые включены во весь каталог и его подкаталоги.
import os
def count(dir, counter=0):
"returns number of files in dir and subdirs"
for pack in os.walk(dir):
for f in pack[2]:
counter += 1
return dir + " : " + str(counter) + "files"
print(count("F:\\python"))
>>> 'F:\\\python' : 12057 files'
Пример 2: Как скопировать все файлы из одного каталога в другой?
Сценарий для упорядочивания вашего компьютера, находит все файлы определенного типа (по умолчанию: pptx) и копирует их в новую папку.
import os
import shutil
from path import path
destination = "F:\\file_copied"
# os.makedirs(destination)
def copyfile(dir, filetype='pptx', counter=0):
"Searches for pptx (or other - pptx is the default) files and copies them"
for pack in os.walk(dir):
for f in pack[2]:
if f.endswith(filetype):
fullpath = pack[0] + "\\" + f
print(fullpath)
shutil.copy(fullpath, destination)
counter += 1
if counter > 0:
print('-' * 30)
print("\t==> Found in: `" + dir + "` : " + str(counter) + " files\n")
for dir in os.listdir():
"searches for folders that starts with `_`"
if dir[0] == '_':
# copyfile(dir, filetype='pdf')
copyfile(dir, filetype='txt')
>>> _compiti18\Compito Contabilità 1\conti.txt
>>> _compiti18\Compito Contabilità 1\modula4.txt
>>> _compiti18\Compito Contabilità 1\moduloa4.txt
>>> ------------------------
>>> ==> Found in: `_compiti18` : 3 files
Пример. 3: Как получить все файлы в текстовом файле
Если вы хотите создать текстовый файл со всеми именами файлов:
import os
mylist = ""
with open("filelist.txt", "w", encoding="utf-8") as file:
for eachfile in os.listdir():
mylist += eachfile + "\n"
file.write(mylist)
Пример: txt со всеми файлами жесткого диска
"""
We are going to save a txt file with all the files in your directory.
We will use the function walk()
"""
import os
# see all the methods of os
# print(*dir(os), sep=", ")
listafile = []
percorso = []
with open("lista_file.txt", "w", encoding='utf-8') as testo:
for root, dirs, files in os.walk("D:\\"):
for file in files:
listafile.append(file)
percorso.append(root + "\\" + file)
testo.write(file + "\n")
listafile.sort()
print("N. of files", len(listafile))
with open("lista_file_ordinata.txt", "w", encoding="utf-8") as testo_ordinato:
for file in listafile:
testo_ordinato.write(file + "\n")
with open("percorso.txt", "w", encoding="utf-8") as file_percorso:
for file in percorso:
file_percorso.write(file + "\n")
os.system("lista_file.txt")
os.system("lista_file_ordinata.txt")
os.system("percorso.txt")
Весь файл C: \ в одном текстовом файле
Это сокращенная версия предыдущего кода. Измените папку, в которой нужно начать поиск файлов, если вам нужно начать с другой позиции. Этот код создает на моем компьютере текстовый файл размером 50 МБ, содержащий менее 500 000 строк с файлами с полным путем.
import os
with open("file.txt", "w", encoding="utf-8") as filewrite:
for r, d, f in os.walk("C:\\"):
for file in f:
filewrite.write(f"{r + file}\n")
Как записать файл со всеми путями в папке типа
С помощью этой функции вы можете создать текстовый файл, который будет иметь имя типа файла, который вы ищете (например, pngfile.txt), со всеми полными путями ко всем файлам этого типа. Думаю, иногда это может быть полезно.
import os
def searchfiles(extension='.ttf', folder='H:\\'):
"Create a txt file with all the file of a type"
with open(extension[1:] + "file.txt", "w", encoding="utf-8") as filewrite:
for r, d, f in os.walk(folder):
for file in f:
if file.endswith(extension):
filewrite.write(f"{r + file}\n")
# looking for png file (fonts) in the hard disk H:\
searchfiles('.png', 'H:\\')
>>> H:\4bs_18\Dolphins5.png
>>> H:\4bs_18\Dolphins6.png
>>> H:\4bs_18\Dolphins7.png
>>> H:\5_18\marketing html\assets\imageslogo2.png
>>> H:\7z001.png
>>> H:\7z002.png
(Новое) Найдите все файлы и откройте их с помощью графического интерфейса tkinter
Я просто хотел добавить в этот 2019 небольшое приложение для поиска всех файлов в каталоге и возможности открывать их двойным щелчком по имени файла в списке.
import tkinter as tk
import os
def searchfiles(extension='.txt', folder='H:\\'):
"insert all files in the listbox"
for r, d, f in os.walk(folder):
for file in f:
if file.endswith(extension):
lb.insert(0, r + "\\" + file)
def open_file():
os.startfile(lb.get(lb.curselection()[0]))
root = tk.Tk()
root.geometry("400x400")
bt = tk.Button(root, text="Search", command=lambda:searchfiles('.png', 'H:\\'))
bt.pack()
lb = tk.Listbox(root)
lb.pack(fill="both", expand=1)
lb.bind("<Double-Button>", lambda x: open_file())
root.mainloop()
Это мешанина из слишком большого количества ответов на вопросы, которые здесь не задаются. Также, возможно, стоит объяснить, в чем заключаются предостережения или рекомендуемые подходы. Мне не лучше знать один способ, чем 20 способов сделать то же самое, если я не знаю, какой из них более уместен и когда.
Хорошо, как можно скорее я посмотрю на свой ответ и постараюсь сделать его более чистым и с более полезной информацией о различиях между методами и т. Д.
Вы не должны определять расширение файла, проверяя, содержит ли имя файла подстроку. Это могло вызвать много неприятностей. Я рекомендую всегда проверять, заканчивается ли имя файла конкретной подстрокой.
Такие компиляции могут быть полезны, но этот ответ, в частности, не добавляет ценности существующим ответам. Чтобы привести пример, [f for f in glob.glob("*.txt")]
эквивалентен glob.glob("*.txt")
и не требует дополнительных разделов в этой статье. Он также очень многословный и с большим количеством пробелов. Можно было бы улучшить, добавив пояснения или указав на различия вместо того, чтобы перечислять еще один вариант.
Спасибо за комментарий, вы, конечно, правы, и я последую вашим советам как можно скорее, чтобы сделать его более полезным, может быть, в эти годы я смогу сделать несколько лучших ответов. Просто дайте мне несколько дней, чтобы доработать его.
files_path = [os.path.abspath(x) for x in os.listdir(directory)]
это не дает полный путь абс, он пропускает directory
в file_path
Большая часть этого ответа состоит из вещей, которые напрямую не связаны с вопросом. Похоже, что большая загрузка (более или менее актуальных) вещей (это слово, но я имел в виду кое-что еще), без структуры, просто сброшена сюда. Напоминает мне, когда я учился в колледже, на экзаменах, что я был неподготовленным (не выучил и не подготовил читерский набор), я написал все, что вспомнил, что было удаленно связано с предметом, надеясь на проходную оценку :(
Хорошо, я признаю, что это слишком долго, и я постараюсь сделать какой-то заказ как можно скорее, но я думаю, что все примеры связаны с вопросом, но я думаю, это все зависит от мнения, поэтому я серьезно отнесусь к вашему комментарию.
Использование генераторов
import os
def get_files(search_path):
for (dirpath, _, filenames) in os.walk(search_path):
for filename in filenames:
yield os.path.join(dirpath, filename)
list_files = get_files('.')
for filename in list_files:
print(filename)
Начиная с версии 3.4 для этого существуют встроенные итераторы , которые намного эффективнее, чем os.listdir()
:
pathlib
: Новое в версии 3.4.
>>> import pathlib
>>> [p for p in pathlib.Path('.').iterdir() if p.is_file()]
Согласно PEP 428, цель библиотеки pathlib
- предоставить простую иерархию классов для обработки путей файловой системы и общих операций, выполняемых пользователями <над ними.
os.scandir()
: Новое в версии 3.5.
>>> import os
>>> [entry for entry in os.scandir('.') if entry.is_file()]
Обратите внимание на то, что os.walk()
использует os.scandir()
вместо <9708277796800> в соответствии с версией . на PEP 471.
Позвольте мне также порекомендовать прочитать комментарий ShadowRanger ниже.
Спасибо! Я думаю, что это единственное решение, которое не возвращает напрямую list
. В качестве альтернативы можно использовать p.name
вместо первого p
, если это необходимо.
Добро пожаловать! Я бы предпочел создавать экземпляры pathlib.Path()
, поскольку у них есть много полезных методов, которые я не хотел бы тратить зря. Вы также можете позвонить им по телефону str(p)
, чтобы узнать имена путей.
Примечание: решение os.scandir
будет более эффективным, чем os.listdir
с проверкой os.path.is_file
и т. > использует API, предоставляемые ОС, которые предоставляют вам информацию is_file
бесплатно во время итерации, без обращения к диску по каждому файлу, чтобы stat
их вообще (в Windows DirEntry
дает вам полную stat
информация бесплатно, в системах * NIX требуется stat
для информации за пределами is_file
, is_dir
и т. д., но DirEntry
кэширует на первом stat
для удобства).
Вы также можете использовать entry.name
, чтобы получить только имя файла, или entry.path
, чтобы получить его полный путь. Больше никаких os.path.join () повсюду.
Мне очень понравился ответ Адамка, в котором предлагается использовать glob()
из одноименного модуля. Это позволяет вам иметь сопоставление с образцом с *
s.
Но, как другие люди указывали в комментариях, glob()
может запутаться из-за несовместимых направлений косой черты. Чтобы помочь с этим, я предлагаю вам использовать функции join()
и expanduser()
в модуле os.path
, а также, возможно, функцию getcwd()
в модуле os
.
В качестве примеров:
from glob import glob
# Return everything under C:\Users\admin that contains a folder called wlp.
glob('C:\Users\admin\*\wlp')
Вышеупомянутое ужасно - путь был жестко запрограммирован и будет работать в Windows только между именем диска и \
, жестко закодированными в путь.
from glob import glob
from os.path import join
# Return everything under Users, admin, that contains a folder called wlp.
glob(join('Users', 'admin', '*', 'wlp'))
Вышеуказанное работает лучше, но оно зависит от имени папки Users
, которое часто встречается в Windows и не так часто встречается в других ОС. Он также полагается на пользователя, имеющего определенное имя, admin
.
from glob import glob
from os.path import expanduser, join
# Return everything under the user directory that contains a folder called wlp.
glob(join(expanduser('~'), '*', 'wlp'))
Это отлично работает на всех платформах.
Еще один отличный пример, который отлично работает на разных платформах и делает что-то немного другое:
from glob import glob
from os import getcwd
from os.path import join
# Return everything under the current directory that contains a folder called wlp.
glob(join(getcwd(), '*', 'wlp'))
Надеюсь, эти примеры помогут вам увидеть мощь некоторых функций, которые вы можете найти в стандартных модулях библиотеки Python.
Дополнительные развлечения: начиная с Python 3.5, **
работает, пока вы устанавливаете recursive = True
. См. Документы здесь: docs.python.org/3.5/library/glob.html#glob.glob
Возвращает список абсолютных путей к файлам, без рекурсии в подкаталоги
L = [os.path.join(os.getcwd(),f) for f in os.listdir('.') if os.path.isfile(os.path.join(os.getcwd(),f))]
Примечание: os.path.abspath(f)
будет несколько более дешевой заменой os.path.join(os.getcwd(),f)
.
Было бы более эффективно, если бы вы начали с cwd = os.path.abspath('.')
, а затем использовали бы cwd
вместо '.'
и os.getcwd()
, чтобы избежать множества избыточных системных вызовов.
def list_files(path):
# returns a list of names (with extension, without full path) of all files
# in folder path
files = []
for name in os.listdir(path):
if os.path.isfile(os.path.join(path, name)):
files.append(name)
return files
Если вы ищете реализацию Python find , я довольно часто использую этот рецепт:
from findtools.find_files import (find_files, Match)
# Recursively find all *.sh files in **/usr/bin**
sh_files_pattern = Match(filetype='f', name='*.sh')
found_files = find_files(path='/usr/bin', match=sh_files_pattern)
for found_file in found_files:
print found_file
Итак, я сделал из него пакет PyPI , а также есть репозиторий GitHub. Я надеюсь, что кто-то сочтет это потенциально полезным для этого кода.
Однострочное решение для получения только списка файлов (без подкаталогов):
filenames = next(os.walk(path))[2]
или абсолютные пути:
paths = [os.path.join(path, fn) for fn in next(os.walk(path))[2]]
Только однострочник, если вы уже import os
. Мне кажется менее лаконичным, чем glob()
.
проблема с glob заключается в том, что папка с именем something.something будет возвращена glob ('/ home / adam /*.*')
В OS X есть нечто, называемое связкой. Это каталог, который обычно следует рассматривать как файл (например, .tar). Вы бы хотели, чтобы они рассматривались как файл или каталог? Использование glob()
рассматривает его как файл. Ваш метод будет рассматривать его как каталог.
Получение полных путей к файлам из каталога и всех его подкаталогов
import os
def get_filepaths(directory):
"""
This function will 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).
"""
file_paths = [] # List which will store all of the full filepaths.
# Walk the tree.
for root, directories, files in os.walk(directory):
for filename in files:
# Join the two strings in order to form the full filepath.
filepath = os.path.join(root, filename)
file_paths.append(filepath) # Add it to the list.
return file_paths # Self-explanatory.
# Run the above function and store its results in a variable.
full_file_paths = get_filepaths("/Users/johnny/Desktop/TEST")
- Путь, который я указал в приведенной выше функции, содержал 3 файла - два из них в корневом каталоге, а другой в подпапке с именем «SUBFOLDER». Теперь вы можете делать такие вещи, как:
-
print full_file_paths
, который распечатает список:-
['/Users/johnny/Desktop/TEST/file1.txt', '/Users/johnny/Desktop/TEST/file2.txt', '/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat']
-
При желании вы можете открывать и читать содержимое или сосредотачиваться только на файлах с расширением «.dat», как в приведенном ниже коде:
for f in full_file_paths:
if f.endswith(".dat"):
print f
/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat
dircache устарел, начиная с версии 2.6: модуль dircache был удален в Python 3.0.
import dircache
list = dircache.listdir(pathname)
i = 0
check = len(list[0])
temp = []
count = len(list)
while count != 0:
if len(list[i]) != check:
temp.append(list[i-1])
check = len(list[i])
else:
i = i + 1
count = count - 1
print temp
Я предпочитаю использовать модуль glob
, поскольку он выполняет сопоставление с образцом и расширение.
import glob
print(glob.glob("/home/adam/*"))
Он интуитивно выполняет сопоставление с образцом
import glob
# All files ending with .txt
print(glob.glob("/home/adam/*.txt"))
# All files ending with .txt with depth of 2 folder
print(glob.glob("/home/adam/*/*.txt"))
Он вернет список с запрошенными файлами:
['/home/adam/file1.txt', '/home/adam/file2.txt', .... ]
это ярлык для listdir + fnmatch docs.python.org/library/fnmatch.html#fnmatch.fnmatch
чтобы уточнить, это не возвращает "полный путь"; он просто возвращает расширение глобуса, каким бы оно ни было. Например. задано /home/user/foo/bar/hello.txt
, то при запуске в каталоге foo
glob("bar/*.txt")
вернет bar/hello.txt
. Бывают случаи, когда вам действительно нужен полный (то есть абсолютный) путь; для этих случаев см. coderhelper.com/questions/51520/…
Связано: найти файлы рекурсивно с помощью glob: coderhelper.com/a/2186565/4561887
не отвечает на этот вопрос. glob.glob("*")
будет.
Есть ли способ гарантировать, что элементы, возвращаемые из glob, являются файлами только ? Я спрашиваю насчет случая, когда файлы могут существовать без расширений (или в других сценариях, где файлы и папки неотличимы только от их строк пути). Я отмечаю, что это подходящее разъяснение здесь, поскольку OP не указывал, есть ли у их файлов расширения.
os.listdir()
вы получите все, что находится в каталоге - файлы и каталоги .9029>
Если вы хотите только файлов, вы можете либо отфильтровать их, используя os.path
:
from os import listdir
from os.path import isfile, join
onlyfiles = [f for f in listdir(mypath) if isfile(join(mypath, f))]
или вы можете использовать os.walk()
, что даст два списка для каждого посещаемого каталога - разделение на <297059104400106> файлов > dirs для вас. Если вам нужен только верхний каталог, вы можете сломать его в первый раз, чтобы получить
from os import walk
f = []
for (dirpath, dirnames, filenames) in walk(mypath):
f.extend(filenames)
break
или, короче:
from os import walk
filenames = next(walk(mypath), (None, None, []))[2] # [] if no file
Немного проще: (_, _, filenames) = walk(mypath).next()
(если вы уверены, что прогулка вернет хотя бы одно значение, которое должно).
Небольшая модификация для хранения полных путей: for (dirpath, dirnames, filenames) в os.walk (mypath): checkum_files.extend (os.path.join (dirpath, filename) для имени файла в именах файлов) break
f.extend(filenames)
фактически не эквивалентен f = f + filenames
. extend
изменит f
на месте, тогда как добавление создает новый список в новом месте памяти. Это означает, что extend
обычно более эффективен, чем +
, но иногда это может привести к путанице, если несколько объектов содержат ссылки на список. Наконец, стоит отметить, что f += filenames
эквивалентно f.extend(filenames)
, не f = f + filenames
.
@misterbee, ваше решение - лучшее, только одно небольшое улучшение: _, _, filenames = next(walk(mypath), (None, None, []))
f += filenames
эквивалентно расширению, а не наоборот ??? Боже.
Второй пример НАМНОГО быстрее
@ ET-CS Вы упоминаете об этом, потому что это быстрее, потому что для первых двух возвращаемых имен для os.walk () не нужны имена, потому что они не нужны?
import os
os.listdir("somedirectory")
вернет список всех файлов и каталогов в "somedirectory".
Это возвращает относительный путь к файлам по сравнению с полным путем, возвращаемым glob.glob
@JIXiang: os.listdir()
всегда возвращает простые имена файлов (не относительные пути). То, что возвращает glob.glob()
, определяется форматом пути входного шаблона.
Относится к Как получить список подкаталогов