Как мне вывести список всех файлов каталога?

avatar
duhhunjonn
8 июля 2010 в 19:31
5949887
21
3466

Как я могу перечислить все файлы каталога в Python и добавить их в list?

Источник
rds
5 января 2012 в 09:32
27

Относится к Как получить список подкаталогов

Ответы (21)

avatar
fralau
24 марта 2019 в 07:07
11

Один мудрый учитель сказал мне однажды, что:

Когда существует несколько устоявшихся способов сделать что-либо, ни один из них не подходит для всех случаев.

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

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, если вы не хотите, чтобы ваши шаблоны всегда придерживались начала или конца имени файла).

avatar
Andy Jazz
9 января 2019 в 10:11
15

Для лучших результатов вы можете использовать метод 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 завершает выполнение функции, но сохраняет ее текущее состояние и возвращает только имя записи, обнаруженной как файл. Все вышесказанное позволяет нам перебрать функцию генератора.

avatar
chris-piekarski
19 октября 2018 в 02:34
4

Для Python 2:

pip install rglob

Затем выполните

import rglob
file_list = rglob.rglob("/home/base/dir/", "*")
print file_list
Eric
30 марта 2021 в 13:45
2

Когда можно избежать внешнего депривации, сделайте это. В чем добавленная стоимость использования внешней зависимости, когда все, что вам нужно, уже есть в языке?

avatar
pah8J
19 июня 2018 в 12:03
10
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

Здесь я использую рекурсивную структуру.

Georgy
17 мая 2019 в 09:37
0

То же самое может быть достигнуто только в одной строке с pathlib: filter(Path.is_file, Path().rglob('*'))

avatar
fhchl
28 марта 2018 в 12:20
5

Другой очень удобочитаемый вариант для 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()]
avatar
CristiFati
23 января 2018 в 03:09
61

Предварительные примечания

  • Хотя в тексте вопроса существует четкое различие между терминами файл и каталог , некоторые могут утверждать, что каталоги на самом деле являются специальными файлами
  • Утверждение: « все файлы каталога » можно интерпретировать двумя способами:
    1. Все прямые (или уровень 1) потомки только
    2. Все потомки во всем дереве каталогов (в том числе в подкаталогах)
  • Когда был задан вопрос, я предполагал, что 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
    


Решения

​​Программные подходы:

  1. [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']
    


  1. [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 (и в некоторых случаях быстрее)


  1. [Python 3]: os. прогулка ( вверху, сверху вниз = True, onerror = None, followlinks = False ) <421170119500>

    Сгенерируйте имена файлов в дереве каталогов, перемещаясь по дереву сверху вниз или снизу вверх. Для каждого каталога в дереве с корнем в каталоге наверху (включая сам наверху ) получается кортеж из трех (dirpath, <4211954339339429>, filenames, filenames). >


    >>> import os
    >>> root_dir = os.path.join(os.getcwd(), "root_dir")  # Specify the full path
    >>> root_dir
    'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir'
    >>>
    >>> walk_generator = os.walk(root_dir)
    >>> root_dir_entry = next(walk_generator)  # First entry corresponds to the root dir (passed as an argument)
    >>> root_dir_entry
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir', ['dir0', 'dir1', 'dir2', 'dir3'], ['file0', 'file1'])
    >>>
    >>> root_dir_entry[1] + root_dir_entry[2]  # Display dirs and files (direct descendants) in a single list
    ['dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1']
    >>>
    >>> [os.path.join(root_dir_entry[0], item) for item in root_dir_entry[1] + root_dir_entry[2]]  # Display all the entries in the previous list by their full path
    ['E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir1', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir3', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\file0', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\file1']
    >>>
    >>> for entry in walk_generator:  # Display the rest of the elements (corresponding to every subdir)
    ...     print(entry)
    ...
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0', ['dir00', 'dir01', 'dir02'], [])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir00', ['dir000'], ['file000'])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir00\\dir000', [], ['file0000'])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir01', [], ['file010', 'file011'])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02', ['dir020'], [])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02\\dir020', ['dir0200'], [])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02\\dir020\\dir0200', [], [])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir1', [], ['file10', 'file11', 'file12'])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2', ['dir20'], ['file20'])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2\\dir20', [], ['file200'])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir3', [], [])
    

    Примечания :

    • Под сценой используется os.scandir (os.listdir в старых версиях)
    • Он выполняет тяжелую работу за счет повторения в подпапках


  1. [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 является предпочтительным
    • Разрешает расширенную фильтрацию по имени (из-за подстановочного знака)


  1. [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']
    

    Примечания :

    • Это один способ достижения нашей цели
    • Это стиль ООП обработки путей
    • Предлагает множество функций


  1. [Python 2]: dircache.listdir (path) ( Python 2 только)


    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
    


  1. [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()
    

    Примечания :


    Вывод :

    [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']]
    


  1. [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']
    

    Примечания :


  1. Установите какой-нибудь (другой) сторонний пакет, который поможет
    • Скорее всего, будет полагаться на одно (или несколько) из вышеперечисленных (возможно, с небольшими изменениями)


Примечания :

  • Код должен быть переносимым (за исключением мест, нацеленных на определенную область - которые отмечены) или крестиком:

    • платформа ( 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 (если функция не работает для одной записи, она будет пропущена), но чем сложнее становится код, тем больше времени потребуется для выполнения
  • Nota bene! Поскольку используется рекурсия, я должен упомянуть, что я провел несколько тестов на своем ноутбуке ( Win 10 x64 ), совершенно не связанных с этой проблемой, и когда уровень рекурсии достигал значений где-то в диапазоне (990 .. 1000) ( предел рекурсии - 1000 (по умолчанию)), я получил StackOverflow :). Если дерево каталогов превышает этот предел (я не эксперт по FS , поэтому я не знаю, возможно ли это вообще), это может быть проблемой.
    Я должен также упомянуть, что я не пытался увеличить предел рекурсии , потому что у меня нет опыта в этой области (насколько я могу его увеличить, прежде чем мне также придется увеличивать стек на уровне ОС ), но теоретически всегда будет возможность сбоя, если глубина каталога больше максимально возможного ограничения рекурсии (на этой машине)

  • Примеры кода предназначены только для демонстрационных целей. Это означает, что я не учел обработку ошибок (я не думаю, что есть try / кроме / <42119592> > else / наконец блок , поэтому код не является надежным (причина в том, чтобы он был как можно более простым и коротким). Для production также должна быть добавлена ​​обработка ошибок

Другие подходы:

  1. Используйте 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
      

    Как правило, этого подхода следует избегать, поскольку, если формат вывода некоторых команд немного отличается между версиями / вариантами ОС , код синтаксического анализа также должен быть адаптирован; не говоря уже о различиях между регионами).

avatar
Vinodh Krishnaraju
11 декабря 2017 в 17:51
2

Я предоставлю образец одного лайнера, в котором исходный путь и тип файла могут быть предоставлены в качестве входных данных. Код возвращает список имен файлов с расширением csv. Используйте . на случай, если необходимо вернуть все файлы. Это также будет рекурсивно сканировать подкаталоги.

[y for x in os.walk(sourcePath) for y in glob(os.path.join(x[0], '*.csv'))]

При необходимости измените расширения файлов и исходный путь.

Martijn Pieters
5 декабря 2018 в 11:09
1

Если вы собираетесь использовать glob, просто используйте glob('**/*.csv', recursive=True). Нет необходимости объединять это с os.walk() для рекурсии (recursive и ** поддерживаются начиная с Python 3.5).

avatar
MarredCheese
7 декабря 2017 в 20:10
3

Вот моя универсальная функция для этого. Он возвращает список путей к файлам, а не имен файлов, поскольку я обнаружил, что это более полезно. У него есть несколько необязательных аргументов, которые делают его универсальным. Например, я часто использую его с такими аргументами, как 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)]
avatar
PythonProgrammi
3 января 2017 в 15:36
1284

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 небольшое приложение для поиска всех файлов в каталоге и возможности открывать их двойным щелчком по имени файла в списке. enter image description here

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()
cs95
27 января 2020 в 09:27
71

Это мешанина из слишком большого количества ответов на вопросы, которые здесь не задаются. Также, возможно, стоит объяснить, в чем заключаются предостережения или рекомендуемые подходы. Мне не лучше знать один способ, чем 20 способов сделать то же самое, если я не знаю, какой из них более уместен и когда.

PythonProgrammi
29 января 2020 в 19:56
3

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

ni1ight
2 марта 2020 в 14:38
1

Вы не должны определять расширение файла, проверяя, содержит ли имя файла подстроку. Это могло вызвать много неприятностей. Я рекомендую всегда проверять, заканчивается ли имя файла конкретной подстрокой.

Turun Ambartanen
12 октября 2020 в 10:20
3

Такие компиляции могут быть полезны, но этот ответ, в частности, не добавляет ценности существующим ответам. Чтобы привести пример, [f for f in glob.glob("*.txt")] эквивалентен glob.glob("*.txt") и не требует дополнительных разделов в этой статье. Он также очень многословный и с большим количеством пробелов. Можно было бы улучшить, добавив пояснения или указав на различия вместо того, чтобы перечислять еще один вариант.

PythonProgrammi
15 октября 2020 в 11:07
1

Спасибо за комментарий, вы, конечно, правы, и я последую вашим советам как можно скорее, чтобы сделать его более полезным, может быть, в эти годы я смогу сделать несколько лучших ответов. Просто дайте мне несколько дней, чтобы доработать его.

Nivesh Krishna
9 декабря 2020 в 18:33
0

files_path = [os.path.abspath(x) for x in os.listdir(directory)] это не дает полный путь абс, он пропускает directory в file_path

CristiFati
18 августа 2021 в 11:04
0

Большая часть этого ответа состоит из вещей, которые напрямую не связаны с вопросом. Похоже, что большая загрузка (более или менее актуальных) вещей (это слово, но я имел в виду кое-что еще), без структуры, просто сброшена сюда. Напоминает мне, когда я учился в колледже, на экзаменах, что я был неподготовленным (не выучил и не подготовил читерский набор), я написал все, что вспомнил, что было удаленно связано с предметом, надеясь на проходную оценку :(

PythonProgrammi
18 августа 2021 в 18:09
0

Хорошо, я признаю, что это слишком долго, и я постараюсь сделать какой-то заказ как можно скорее, но я думаю, что все примеры связаны с вопросом, но я думаю, это все зависит от мнения, поэтому я серьезно отнесусь к вашему комментарию.

avatar
shantanoo
2 декабря 2016 в 07:01
6

Использование генераторов

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)
avatar
SzieberthAdam
18 июня 2015 в 20:58
90

Начиная с версии 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 ниже.

jeromej
22 июня 2015 в 12:36
1

Спасибо! Я думаю, что это единственное решение, которое не возвращает напрямую list. В качестве альтернативы можно использовать p.name вместо первого p, если это необходимо.

SzieberthAdam
13 июля 2015 в 14:56
1

Добро пожаловать! Я бы предпочел создавать экземпляры pathlib.Path(), поскольку у них есть много полезных методов, которые я не хотел бы тратить зря. Вы также можете позвонить им по телефону str(p), чтобы узнать имена путей.

ShadowRanger
20 ноября 2015 в 22:38
6

Примечание: решение os.scandir будет более эффективным, чем os.listdir с проверкой os.path.is_file и т. > использует API, предоставляемые ОС, которые предоставляют вам информацию is_file бесплатно во время итерации, без обращения к диску по каждому файлу, чтобы stat их вообще (в Windows DirEntry дает вам полную stat информация бесплатно, в системах * NIX требуется stat для информации за пределами is_file, is_dir и т. д., но DirEntry кэширует на первом stat для удобства).

user136036
28 марта 2017 в 20:26
1

Вы также можете использовать entry.name, чтобы получить только имя файла, или entry.path, чтобы получить его полный путь. Больше никаких os.path.join () повсюду.

avatar
ArtOfWarfare
9 июля 2014 в 11:43
49

Мне очень понравился ответ Адамка, в котором предлагается использовать 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.

ArtOfWarfare
26 января 2015 в 03:24
4

Дополнительные развлечения: начиная с Python 3.5, ** работает, пока вы устанавливаете recursive = True. См. Документы здесь: docs.python.org/3.5/library/glob.html#glob.glob

avatar
The2ndSon
13 июня 2014 в 16:26
11

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

L = [os.path.join(os.getcwd(),f) for f in os.listdir('.') if os.path.isfile(os.path.join(os.getcwd(),f))]
ShadowRanger
6 мая 2017 в 00:14
2

Примечание: os.path.abspath(f) будет несколько более дешевой заменой os.path.join(os.getcwd(),f).

Martijn Pieters
5 декабря 2018 в 10:46
1

Было бы более эффективно, если бы вы начали с cwd = os.path.abspath('.'), а затем использовали бы cwd вместо '.' и os.getcwd(), чтобы избежать множества избыточных системных вызовов.

avatar
Apogentus
10 июня 2014 в 16:16
39
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 
avatar
Yauhen Yakimovich
10 апреля 2014 в 14:09
25

Если вы ищете реализацию 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. Я надеюсь, что кто-то сочтет это потенциально полезным для этого кода.

avatar
Remi
18 января 2014 в 17:42
177

Однострочное решение для получения только списка файлов (без подкаталогов):

filenames = next(os.walk(path))[2]

или абсолютные пути:

paths = [os.path.join(path, fn) for fn in next(os.walk(path))[2]]
ArtOfWarfare
28 ноября 2014 в 20:22
7

Только однострочник, если вы уже import os. Мне кажется менее лаконичным, чем glob().

Remi
1 декабря 2014 в 09:08
4

проблема с glob заключается в том, что папка с именем something.something будет возвращена glob ('/ home / adam /*.*')

ArtOfWarfare
1 декабря 2014 в 19:44
6

В OS X есть нечто, называемое связкой. Это каталог, который обычно следует рассматривать как файл (например, .tar). Вы бы хотели, чтобы они рассматривались как файл или каталог? Использование glob() рассматривает его как файл. Ваш метод будет рассматривать его как каталог.

avatar
Johnny
11 октября 2013 в 00:55
144

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

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

avatar
shaji
25 июля 2012 в 10:25
2

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
avatar
adamk
9 июля 2010 в 18:13
2112

Я предпочитаю использовать модуль 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', .... ]
Stefano
1 июля 2011 в 13:03
19

это ярлык для listdir + fnmatch docs.python.org/library/fnmatch.html#fnmatch.fnmatch

michael
16 августа 2016 в 12:07
48

чтобы уточнить, это не возвращает "полный путь"; он просто возвращает расширение глобуса, каким бы оно ни было. Например. задано /home/user/foo/bar/hello.txt, то при запуске в каталоге foo glob("bar/*.txt") вернет bar/hello.txt. Бывают случаи, когда вам действительно нужен полный (то есть абсолютный) путь; для этих случаев см. coderhelper.com/questions/51520/…

Gabriel Staples
3 сентября 2018 в 03:25
1

Связано: найти файлы рекурсивно с помощью glob: coderhelper.com/a/2186565/4561887

Jean-François Fabre
17 мая 2019 в 18:36
9

не отвечает на этот вопрос. glob.glob("*") будет.

aamailhot
11 августа 2021 в 21:57
0

Есть ли способ гарантировать, что элементы, возвращаемые из glob, являются файлами только ? Я спрашиваю насчет случая, когда файлы могут существовать без расширений (или в других сценариях, где файлы и папки неотличимы только от их строк пути). Я отмечаю, что это подходящее разъяснение здесь, поскольку OP не указывал, есть ли у их файлов расширения.

avatar
pycruft
8 июля 2010 в 21:01
5357

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

misterbee
14 июля 2013 в 20:56
112

Немного проще: (_, _, filenames) = walk(mypath).next() (если вы уверены, что прогулка вернет хотя бы одно значение, которое должно).

okigan
23 сентября 2013 в 21:31
10

Небольшая модификация для хранения полных путей: for (dirpath, dirnames, filenames) в os.walk (mypath): checkum_files.extend (os.path.join (dirpath, filename) для имени файла в именах файлов) break

Benjamin Hodgson
22 октября 2013 в 08:55
176

f.extend(filenames) фактически не эквивалентен f = f + filenames. extend изменит f на месте, тогда как добавление создает новый список в новом месте памяти. Это означает, что extend обычно более эффективен, чем +, но иногда это может привести к путанице, если несколько объектов содержат ссылки на список. Наконец, стоит отметить, что f += filenames эквивалентно f.extend(filenames), не f = f + filenames.

bgusach
5 марта 2015 в 07:36
35

@misterbee, ваше решение - лучшее, только одно небольшое улучшение: _, _, filenames = next(walk(mypath), (None, None, []))

Umagon
12 июля 2020 в 09:18
2

f += filenames эквивалентно расширению, а не наоборот ??? Боже.

FloPinguin
12 августа 2020 в 18:52
0

Второй пример НАМНОГО быстрее

Timo
24 декабря 2020 в 10:53
0

@ ET-CS Вы упоминаете об этом, потому что это быстрее, потому что для первых двух возвращаемых имен для os.walk () не нужны имена, потому что они не нужны?

coder
15 июля 2021 в 13:16
0

Петиция, чтобы этот ответ был принятым ответом! (этот ответ упоминается в этом сообщении блога stackoverflow )

avatar
sepp2k
8 июля 2010 в 19:35
919
import os
os.listdir("somedirectory")

вернет список всех файлов и каталогов в "somedirectory".

xji
17 мая 2016 в 14:32
12

Это возвращает относительный путь к файлам по сравнению с полным путем, возвращаемым glob.glob

mklement0
30 ноября 2016 в 18:14
24

@JIXiang: os.listdir() всегда возвращает простые имена файлов (не относительные пути). То, что возвращает glob.glob(), определяется форматом пути входного шаблона.