Как сделать скрипт более универсальным
Написал небольшой скрипт, который находит все файлы на диске (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 шт):
ну на питоне уж сами докрутите, но такие вещи решаются вызовом функции поиска файлов и папок из той же самой функции (т.е. через рекурсивный вызов)
вот пример на с++, важен не язык, а подход
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);
}
т.е. надо
- найти все файлы и папки в текущей папке
- если найденный объект является папкой, то сформировать ее полный путь
- вызвать ту же самую функцию для нового пути
т.е. получается такая вложенная (рекурсивная) функция поиска (перебора) файлов и папок
P.S.
если вам надо искать только какие-то заданные файлы (по имени или размеру), то все равно поиск надо делать по *.*, чтобы найти и все папки и уже потом фильтровать найденные файлы
Для этого есть 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} Кб')
Еще вариант с 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} Кб")