Как сделать скрипт более универсальным

Написал небольшой скрипт, который находит все файлы на диске (CD) и определяет размер этих фалов. Проблема лишь в том, что будет он работать только, если вложенных папок и файлов не больше 1. Как можно сделать этот скрипт более универсальным, не зависящем от количества вложенных папок?

import os
import psutil


file_name = 'DISK 1'
DISK = "G:"
disk_path = "G:\\" # Заходим в корневой каталог


folders = os.listdir(disk_path)  # Список всех файлов на диске

for folder in folders:  # Заходим в каждую папку на диске
    folder_path = os.path.join(disk_path, folder) # Путь до папок
    files = os.listdir(folder_path) # Определяем название файлов в папке
    for file in files: # Для каждого найденного файла в папке
        file_path = os.path.join(folder_path, file) # Путь до файла
        size = os.stat(file_path).st_size  # Размер файла
        size = size / 2 ** 10          # Переводим байты в Кб (для Мб 2 ** 20)
        with open(f'{file_name}.txt', 'a') as f: # Запись в текстовый файл
            f.write(f"{file_path:<100}{size:.2f} Кб"+'\n')

# Объем занятого пространства на диске
occupied = psutil.disk_usage(DISK).used/(1024*1024) 
with open(f'{file_name}.txt', 'a') as f:
    f.write('\n' + f"Объем занятого пространства на диске {occupied:.4} Мб"+'\n')

Пример вывода:

G:\ЖРГА.687253.075 Т1М\Gerber.zip                             26.28 Кб
G:\ЖРГА.687253.075 Т2М\Drill.zip                              0.98 Кб
G:\ЖРГА.687253.075 Т5М\Data_production.zip                    7.89 Кб

Объем занятого пространства на диске 29.89 Мб

Ответы (3 шт):

Автор решения: Zhihar

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

вот пример на с++, важен не язык, а подход

void myfunc_GetAllFiles(const std::string& path)
{
    // сформировать маску для поиска всех файлов и папок
    const std::string mask = path + "\\*.*";

    // найти все файлы
    WIN32_FIND_DATA findFileData;
    HANDLE findFileHandle = FindFirstFile(mask.c_str(), &findFileData);

    if (findFileHandle == INVALID_HANDLE_VALUE)
        return;

    do
    {
        // не рассматривать служебные объекты
        if ((strcmp(findFileData.cFileName, ".") == 0) || (strcmp(findFileData.cFileName, "..") == 0))
            continue;

        // если найдена папка - вызвать поиск в папке
        if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
        {
            // сформировать полное имя папки
            const std::string path_new = path + std::string("\\") + std::string(findFileData.cFileName);

            // искать в папке
            myfunc_GetAllFiles(path_new);
        }

        // вывести название найденного файла (тут любая логика)
        cout << findFileData.cFileName << endl;
    }
    while (::FindNextFile(findFileHandle, &findFileData) != 0);

    ::FindClose(findFileHandle);
}    

т.е. надо

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

т.е. получается такая вложенная (рекурсивная) функция поиска (перебора) файлов и папок

P.S.

если вам надо искать только какие-то заданные файлы (по имени или размеру), то все равно поиск надо делать по *.*, чтобы найти и все папки и уже потом фильтровать найденные файлы

→ Ссылка
Автор решения: n1tr0xs

Для этого есть os.walk:

import os

path = 'D:\\'

for dirpath, dirnames, filenames in os.walk(path):
    for filename in filenames:
        file_path = os.path.join(dirpath, filename)
        file_size = os.stat(file_path).st_size / 2**10
        print(f'{file_path} {file_size} Кб')
→ Ссылка
Автор решения: insolor

Еще вариант с pathlib:

from pathlib import Path

root_path = Path('G:')

for path in Path.rglob(root_path, '*'):
    if path.is_file():
        print(f"{path} {path.stat().st_size / 1024:.3f} Кб")
→ Ссылка