Файлы подсчета Python в каталоге и во всех его подкаталогах

Я пытаюсь подсчитать все файлы в папке и во всех ее подпапках Например, если моя папка выглядит так:

file1.txt
subfolder1/
├── file2.txt
├── subfolder2/
│   ├── file3.txt
│   ├── file4.txt
│   └── subfolder3/
│       └── file5.txt
└── file6.txt
file7.txt

Я хотел бы получить число 7.

Первое, что я попробовал, это рекурсивная функция, которая считает все файлы и вызывает себя для каждой папки.

def get_file_count(directory: str) -> int:

    count = 0

    for filename in os.listdir(directory):

        file = (os.path.join(directory, filename))

        if os.path.isfile(file):
            count += 1

        elif os.path.isdir(file):
            count += get_file_count(file)

    return count

Этот способ работает, но требует много времени для больших каталогов.

Я также вспомнил эта почта, который показывает быстрый способ подсчета общего размера папки с помощью win32com, и мне стало интересно, предлагает ли эта библиотека способ сделать то, что я искал. Но после поиска я нашел только это

fso = com.Dispatch("Scripting.FileSystemObject")
folder = fso.GetFolder(".")
size = folder.Files.Count

Но это возвращает только количество файлов только в целевой папке (а не в ее подпапках)

Итак, знаете ли вы, есть ли в питоне оптимальная функция, которая возвращает количество файлов в папке и всех ее подпапках?

Вы пытались объединить две реализации?

weasel 17.05.2022 14:30
os.walk может помочь здесь.
Scott Hunter 17.05.2022 14:30

Нет, @weasel, как вы думаете, это уменьшит время выполнения?

crazycat256 17.05.2022 14:32

Можете ли вы количественно оценить «много времени» на примере количества файлов, задействованных в поиске? Я только что провел тест с использованием шарик(), который анализирует сильно вложенную структуру каталогов и обнаруживает более 160 000 простых файлов за 2,5 секунды.

Lancelot du Lac 17.05.2022 15:01

Первая функция нашла 61 000 файлов за 40 лет @LancelotduLac

crazycat256 17.05.2022 15:05
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
Четыре эффективных способа центрирования блочных элементов в CSS
Четыре эффективных способа центрирования блочных элементов в CSS
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то...
2
5
43
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

я использовал os.walk()

это мой образец, надеюсь, он вам поможет

def file_dir():
    directories = []
    res = {}
    cwd = os.getcwd()
    for root, dirs, files in os.walk(cwd):
        for file in files:
            if file.endswith(".tsv"):
                directories.append(os.path.join(root, file))
    res['dir'] = directories
    return res

Я не знаю почему if file.endswith(".tsv"): но если я уберу эту строчку, твой код будет работать отлично

crazycat256 17.05.2022 17:33
Ответ принят как подходящий

IIUC, вы можете просто сделать

sum(len(files) for _, _, files in os.walk('path/to/folder'))

или, возможно, чтобы избежать len для, возможно, немного лучшей производительности:

sum(1 for _, _, files in os.walk('folder_test') for f in files)

вы также можете напрямую использовать команду:

find DIR_NAME -type f | wc -l

это возвращает количество всех файлов С os.system() это можно сделать из python.

Эта команда работает на какой ОС?

crazycat256 17.05.2022 14:58

в частности, это команда Linux. Это должно работать и для Mac. К сожалению, у меня нет опыта использования Windows, но, например, здесь вы можете найти соответствующую команду Windows.

LW42 17.05.2022 15:14

Другое решение с использованием библиотек os и Path:

from pathlib import Path
from os.path import isfile

len([x for x in Path('./dir1').rglob('*') if isfile(x)])

Правильный способ - использовать os.walk, как указывали другие, но дать другое решение, которое максимально похоже на ваш оригинал:

Вы можете использовать os.scandir, чтобы избежать затрат на построение всего списка, это должно быть значительно быстрее:

def get_file_count(directory: str) -> int:
    count = 0

    for entry in os.scandir(directory):
        if entry.is_file():
            count += 1

        elif entry.is_dir():
            count += get_file_count(os.path.join(directory, entry.name))

    return count

Этот код покажет количество всех записей каталога, которые не являются каталогами (например, простые файлы, символические ссылки) из указанного корня.

Включает время и фактическое имя пути, используемое в тесте:

from glob import glob, escape
import os
import time


def get_file_count(directory: str) -> int:
    count = 0
    for filename in glob(os.path.join(escape(directory), '*')):
        if os.path.isdir(filename):
            count += get_file_count(filename)
        else:
            count += 1
    return count

start = time.perf_counter()
count = get_file_count('/Volumes/G-DRIVE Thunderbolt 3')
end = time.perf_counter()

print(count)
print(f'{end-start:.2f}s')

Выход:

166231
2.38s

Другие вопросы по теме