move_files.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import csv
  2. import os
  3. import shutil
  4. from dataclasses import dataclass
  5. from datetime import datetime
  6. from pathlib import Path
  7. @dataclass(frozen=True)
  8. class MoveFilesResult:
  9. moved_count: int
  10. skipped_count: int
  11. missing_client_count: int
  12. @dataclass(frozen=True)
  13. class RefreshAndMoveResult:
  14. xml_count: int
  15. file_count: int
  16. moved_count: int
  17. skipped_count: int
  18. missing_client_count: int
  19. def default_desktop() -> Path:
  20. user_profile = Path(os.environ.get("USERPROFILE", str(Path.home())))
  21. return user_profile / "Desktop"
  22. def read_csv(csv_path: Path) -> list[dict[str, str]]:
  23. if not csv_path.is_file():
  24. raise ValueError(f"Die CSV-Datei existiert nicht: {csv_path}")
  25. with csv_path.open("r", newline="", encoding="latin-1") as csv_file:
  26. return list(csv.DictReader(csv_file, delimiter=";"))
  27. def rename_existing_target(target: Path) -> Path:
  28. created_at = datetime.fromtimestamp(target.stat().st_birthtime)
  29. timestamp = created_at.strftime("%Y%m%d-%H%M%S")
  30. renamed_target = target.with_name(f"{target.stem}_{timestamp}{target.suffix}")
  31. counter = 1
  32. while renamed_target.exists():
  33. renamed_target = target.with_name(f"{target.stem}_{timestamp}_{counter}{target.suffix}")
  34. counter += 1
  35. target.rename(renamed_target)
  36. return renamed_target
  37. def move_files(
  38. files_csv: Path,
  39. clients_csv: Path,
  40. desktop_directory: Path | None = None,
  41. ) -> MoveFilesResult:
  42. desktop_directory = desktop_directory or default_desktop()
  43. client_rows = read_csv(clients_csv)
  44. client_names = {
  45. row.get("ParticipantName", "").strip(): row.get("Kunde", "").strip()
  46. for row in client_rows
  47. if row.get("ParticipantName", "").strip() and row.get("Kunde", "").strip()
  48. }
  49. moved_count = 0
  50. skipped_count = 0
  51. missing_client_count = 0
  52. for row in read_csv(files_csv):
  53. participant_name = row.get("ParticipantName", "").strip()
  54. source = Path(row.get("FilePath", "").strip())
  55. customer = client_names.get(participant_name)
  56. if not customer:
  57. missing_client_count += 1
  58. continue
  59. if not source.is_file():
  60. skipped_count += 1
  61. continue
  62. target_directory = desktop_directory / "PC-Visit" / customer
  63. target_directory.mkdir(parents=True, exist_ok=True)
  64. target = target_directory / source.name
  65. if source.resolve() == target.resolve():
  66. skipped_count += 1
  67. continue
  68. if target.exists():
  69. renamed_target = rename_existing_target(target)
  70. print(f"Vorhandene Datei umbenannt: {target} -> {renamed_target}")
  71. shutil.move(str(source), str(target))
  72. print(f"Datei verschoben: {source} -> {target}")
  73. moved_count += 1
  74. return MoveFilesResult(
  75. moved_count=moved_count,
  76. skipped_count=skipped_count,
  77. missing_client_count=missing_client_count,
  78. )
  79. def refresh_and_move(
  80. directory: Path,
  81. files_csv: Path,
  82. clients_csv: Path,
  83. desktop_directory: Path | None = None,
  84. ignore_timestamp: bool = False,
  85. ) -> RefreshAndMoveResult:
  86. from files import run as run_files
  87. files_result = run_files(directory, files_csv, ignore_timestamp=ignore_timestamp)
  88. move_result = move_files(files_csv, clients_csv, desktop_directory)
  89. return RefreshAndMoveResult(
  90. xml_count=files_result.xml_count,
  91. file_count=files_result.row_count,
  92. moved_count=move_result.moved_count,
  93. skipped_count=move_result.skipped_count,
  94. missing_client_count=move_result.missing_client_count,
  95. )