Загрузка данных
import os
import re
import shutil
from pathlib import Path
# === НАСТРОЙКИ ===
SOURCE_DIR = Path(r"C:\Путь\к\твоей\исходной\папке")
OUTPUT_DIR = Path(r"C:\Путь\к\папке\Итог_2023")
YEAR = "2023"
# Список папок, которые нужно ОСТАВИТЬ (в нижнем регистре для надежного сравнения)
KEEP_FOLDERS = {
"мр и др": "МР и др",
"мр и др.": "МР и др",
"рпд": "РПД",
"рпп": "РПП"
}
# Регулярка для поиска кода направления (например, "54.03.01 Дизайн")
OP_CODE_REGEX = re.compile(r"^(\d{2}\.\d{2}\.\d{2})\b")
# Регулярка для удаления цифр в начале папок ("3 РПД" -> "РПД")
LEADING_NUM_REGEX = re.compile(r"^\d+[\.\s_-]*")
def move_file_safely(src_file: Path, target_dir: Path):
"""Перемещает файл в нужную папку, добавляя счетчик, если имя уже занято."""
target_path = target_dir / src_file.name
counter = 1
while target_path.exists():
target_path = target_dir / f"{src_file.stem}_{counter}{src_file.suffix}"
counter += 1
shutil.move(str(src_file), str(target_path))
def process_profile_content(profile_dir: Path):
"""Оставляет только МР и др, РПД, РПП, а из остальных выносит файлы в корень."""
for item in list(profile_dir.iterdir()):
if not item.is_dir():
continue
# Убираем номер в начале названия ("8 МР и др" -> "МР и др")
clean_name = LEADING_NUM_REGEX.sub("", item.name).strip()
clean_name_lower = clean_name.lower()
# 1. Если это одна из 3 папок, которые нужно оставить
if clean_name_lower in KEEP_FOLDERS:
standard_name = KEEP_FOLDERS[clean_name_lower]
target_dir = profile_dir / standard_name
if item != target_dir:
if not target_dir.exists():
item.rename(target_dir)
print(f" [Переименована] '{item.name}' -> '{standard_name}'")
else:
# Если папка уже есть, сливаем содержимое в неё
for sub_item in item.iterdir():
if sub_item.is_file():
move_file_safely(sub_item, target_dir)
elif sub_item.is_dir():
shutil.move(str(sub_item), str(target_dir / sub_item.name))
shutil.rmtree(item)
print(f" [Объединена] '{item.name}' -> '{standard_name}'")
# 2. Все остальные папки (Описание ОП, АУП, Анн РПД, Графики УП и т.д.)
else:
files_moved = 0
# rglob("*") достанет все файлы, даже если внутри были еще подпапки
for sub_item in item.rglob("*"):
if sub_item.is_file() and sub_item.name.lower() not in ("thumbs.db", ".ds_store", "desktop.ini"):
move_file_safely(sub_item, profile_dir)
files_moved += 1
# Удаляем саму папку после выноса файлов
shutil.rmtree(item)
print(f" [Распакована и удалена] '{item.name}' (вынесено файлов: {files_moved})")
def main():
if not SOURCE_DIR.exists():
print(f"Ошибка: Исходная папка {SOURCE_DIR} не найдена!")
return
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
for root, dirs, _ in os.walk(SOURCE_DIR):
root_path = Path(root)
match = OP_CODE_REGEX.match(root_path.name)
if match:
op_code = match.group(1)
for profile_dir in root_path.iterdir():
if profile_dir.is_dir():
profile_name = profile_dir.name.strip()
new_folder_name = f"{YEAR} {op_code} {profile_name}"
target_profile_path = OUTPUT_DIR / new_folder_name
print(f"\nОбработка: {new_folder_name}")
if target_profile_path.exists():
shutil.rmtree(target_profile_path)
shutil.copytree(profile_dir, target_profile_path)
process_profile_content(target_profile_path)
dirs.clear()
print("\nГотово! Все папки собраны в:", OUTPUT_DIR)
if __name__ == "__main__":
main()