Python Grundkurs Teil 006: Ordnername als Präfix
Worum geht es in diesem Teil?
In diesem Teil des Python-Grundkurses verwenden wir den Namen eines Ordners automatisch als Präfix für die direkt darin enthaltenen Dateien.
Aus diesen Dateien:
Rechnungen\beleg001.pdf
Rechnungen\beleg002.pdf

Vorher
werden beispielsweise:
Rechnungen\Rechnungen_beleg001.pdf
Rechnungen\Rechnungen_beleg002.pdf

Nachher
Der Ordnername selbst bleibt unverändert. Mögliche Unterordner werden nicht umbenannt und nicht rekursiv durchsucht.
Wir erstellen zwei Varianten:
- Die erste Variante verarbeitet die direkt enthaltenen Dateien aller direkten Unterordner eines Hauptordners.
- Die zweite Variante wird über das Windows-Menü Senden an gestartet und verarbeitet die direkt enthaltenen Dateien der ausgewählten Ordner.
Was ist das Ziel?
Die Python-Skripte sollen Dateien übersichtlich und kontrolliert umbenennen. Der Name des jeweiligen Ordners wird zusammen mit einem Unterstrich vor den bisherigen Dateinamen gesetzt.
Bereits passend benannte Dateien werden übersprungen. Existiert der geplante Zielname schon, findet ebenfalls keine Umbenennung statt. Im Testmodus lässt sich der vollständige Ablauf zunächst ohne Änderungen kontrollieren.
Warum ist dieser Teil wichtig?
In diesem Tutorial verbinden wir mehrere wichtige Python-Grundlagen:
Path.cwd()liefert den aktuellen Arbeitsordner.iterdir()ermittelt direkt enthaltene Elemente.is_dir()undis_file()unterscheiden Ordner und Dateien.ordner.nameliefert den Namen, der als Präfix verwendet wird.- Der Operator
/setzt mitPathOrdner und Dateinamen zu einem vollständigen Pfad zusammen. casefold()undstartswith()erkennen ein bereits vorhandenes Präfix ohne Beachtung der Groß- und Kleinschreibung.exists()schützt bereits vorhandene Zieldateien.- Dictionaries speichern die geplanten Umbenennungen mit Quelle und Ziel.
rename()führt die eigentliche Umbenennung erst nach allen Prüfungen aus.tryundexceptfangen typische Datei- und Ordnerfehler kontrolliert ab.
Hinweis zur Kursreihe
Dieses Tutorial gehört zum Python-Grundkurs. Der Aufbau orientiert sich an den entsprechenden Teilen für Batch und PowerShell 7. Dadurch lassen sich die unterschiedlichen Schreibweisen und Möglichkeiten der drei Programmiersprachen besonders gut vergleichen.
Downloads zu diesem Teil
Download Python Grundkurs: 006_Ordnername_als_Praefix als ZIP-Datei.Entpacken nach:
C:\TOPTORIALS_CODE\020_Python_Grundkurs
Dadurch entsteht dieser Hauptordner:
C:\TOPTORIALS_CODE\020_Python_Grundkurs\006_Ordnername_als_Praefix
Testumgebung zum Mitmachen
Für gefahrlose Tests kann wieder die vorbereitete Testumgebung verwendet werden.
Testumgebung für Windows-Automatisierung:Download TOPTORIALS_Testdaten_Windows_Automatisierung_V001.zip
Entpacken nach:
C:\TOPTORIALS_CODE\1000_TESTBEREICH
Für Python befindet sich der passende Testbereich anschließend unter:
C:\TOPTORIALS_CODE\1000_TESTBEREICH\TOPTORIALS_Testdaten_Windows_Automatisierung_Python_V001\006_Ordnername_als_Praefix
Sicherheitshinweis
Wichtig:Teste Skripte zum Umbenennen zuerst immer mit Kopien unwichtiger Dateien. Die mitgelieferten Starter-Batchdateien enthalten im Dateinamen zunächst _test. Dadurch wird nur angezeigt und protokolliert, was Python umbenennen würde.
Für den Echtmodus wird _test aus dem Namen der tatsächlichen Starter-Batchdatei entfernt. Zusätzlich muss die Sicherheitsabfrage mit JA bestätigt werden.
Enthaltene Ordner und Dateien
006_Ordnername_als_Praefix
│
├── 01_Unterordnerinhalt_mit_Ordnername_umbenennen
│ ├── 006_unterordnerinhalt_mit_ordnername_umbenennen.py
│ └── 006_unterordnerinhalt_mit_ordnername_umbenennen_starter_batch_test.bat
│
└── 02_SendTo_Ordnerinhalt_mit_Ordnername_umbenennen
├── 006_sendto_ordnerinhalt_mit_ordnername_umbenennen.py
└── 006_sendto_ordnerinhalt_mit_ordnername_umbenennen_starter_batch_test.bat
Wie wird das Präfix gebildet?
Der Name des gerade verarbeiteten Ordners wird mit einem Unterstrich verbunden:
praefix = ordner.name + "_"
Heißt der Ordner beispielsweise Rechnungen, lautet das Präfix Rechnungen_.
Der neue Dateiname entsteht anschließend aus Präfix und bisherigem Dateinamen:
neuer_name = praefix + datei.name
Mit dem Path-Operator / wird daraus der vollständige Zielpfad:
ziel_pfad = ordner / neuer_name
Testmodus und Echtmodus
Die Starter-Batchdatei erkennt am eigenen Dateinamen, ob _test enthalten ist.
- Mit
_testwird Python zusätzlich mit dem Argument--testgestartet. - Ohne
_teststartet das Skript im Echtmodus.
Die Python-Skripte sammeln zuerst alle gültigen Umbenennungen in der Liste plaene. Jeder Plan ist ein Dictionary mit Informationen wie Quelle, altem Namen, neuem Namen und Zielpfad. Erst danach werden die Pläne entweder nur angezeigt oder wirklich ausgeführt.
Ausgabe und Protokoll
Nach dem Prüfen der Dateien kann die Ausgabe an verschiedene Ziele gesendet werden:
- nur auf den Bildschirm,
- zusätzlich in eine Protokolldatei,
- zusätzlich in die Windows-Zwischenablage oder
- gleichzeitig an alle drei Ziele.
In der Standardkonfiguration sind Logdatei und Zwischenablage ausgeschaltet. Sehr lange Pfade werden bei geplanten und ausgeführten Umbenennungen auf mehrere Zeilen verteilt:
WÜRDE UMBENENNEN:
"C:\...\Rechnungen\beleg001.pdf"
zu
"C:\...\Rechnungen\Rechnungen_beleg001.pdf"
---
Innerhalb eines Python-Textes erzeugt \n einen Zeilenumbruch. Dadurch bleiben auch lange Quell- und Zielpfade gut lesbar.
Variante 1: Inhalte der direkten Unterordner umbenennen
Bei dieser Variante liegen das Python-Skript und die Starter-Batchdatei gemeinsam in einem Hauptordner. Das Skript verwendet den aktuellen Arbeitsordner, sucht darin alle direkten Unterordner und verarbeitet jeweils nur deren direkt enthaltene Dateien.
Eine mögliche Ausgangssituation sieht so aus:
01_Unterordnerinhalt_mit_Ordnername_umbenennen
│
├── Rechnungen
│ ├── beleg001.pdf
│ └── beleg002.pdf
│
└── Scans
├── dokument001.jpg
└── dokument002.jpg
Im Testmodus würde das Skript unter anderem folgende Ziele planen:
Rechnungen\Rechnungen_beleg001.pdf
Rechnungen\Rechnungen_beleg002.pdf
Scans\Scans_dokument001.jpg
Scans\Scans_dokument002.jpg
Vollständiges Python-Skript
# ============================================================
# TOPTORIALS OFFICE - Python Grundkurs
# Script: 006_unterordnerinhalt_mit_ordnername_umbenennen.py
# Beschreibung: Benennt Dateien in Unterordnern mit dem jeweiligen Ordnernamen als Präfix um.
# Autor: Chris
# YouTube: https://www.youtube.com/@TOPTORIALS-OFFICE
# Webseite: https://www.toptorials.com
# Version: 1.0
# Stand: 2026-08-18
# ============================================================
from datetime import datetime
from pathlib import Path
import subprocess
import sys
print()
basis_ordner = Path.cwd()
testmodus = "--test" in sys.argv
# ------------------------------------------------------------
# Welche zusätzliche Ausgabe soll erstellt werden?
# Wichtig: Immer nur EINE der folgenden Varianten aktiv lassen.
# ------------------------------------------------------------
# Variante 1: Nur Bildschirmausgabe
logdatei_erstellen = False
zwischenablage_verwenden = False
# Variante 2: Logdatei erstellen
# logdatei_erstellen = True
# zwischenablage_verwenden = False
# Variante 3: Nur in die Zwischenablage kopieren
# logdatei_erstellen = False
# zwischenablage_verwenden = True
# Variante 4: Logdatei erstellen und in die Zwischenablage kopieren
# logdatei_erstellen = True
# zwischenablage_verwenden = True
# ------------------------------------------------------------
# Modus, Zähler und Protokoll vorbereiten
# ------------------------------------------------------------
if testmodus:
modus_text = "TESTMODUS"
else:
modus_text = "ECHTMODUS"
anzahl_umbenannt = 0
anzahl_uebersprungen = 0
anzahl_fehler = 0
anzahl_ordner = 0
protokoll = []
plaene = []
protokoll.append(
"Dateien in Unterordnern werden mit dem jeweiligen "
"Ordnernamen als Präfix umbenannt."
)
protokoll.append(f"Modus: {modus_text}")
protokoll.append(f"Hauptordner: {basis_ordner}")
protokoll.append("")
print(
"Dateien in Unterordnern werden mit dem jeweiligen "
"Ordnernamen als Präfix umbenannt..."
)
print()
print("Hauptordner:")
print(basis_ordner)
print()
print(f"Modus: {modus_text}")
print()
# ------------------------------------------------------------
# Direkt enthaltene Unterordner erfassen
# Tiefere Unterordner werden nicht durchsucht.
# ------------------------------------------------------------
unterordner = []
try:
for pfad in basis_ordner.iterdir():
if pfad.is_dir():
unterordner.append(pfad)
except OSError as fehler:
print(
"FEHLER: Die Unterordner konnten nicht gelesen werden. "
f"Grund:\n{fehler}"
)
print()
input("Drücke Enter zum Beenden")
sys.exit()
# ------------------------------------------------------------
# Dateien prüfen und Umbenennungen planen
# ------------------------------------------------------------
for ordner in unterordner:
praefix = ordner.name + "_"
dateien = []
try:
for pfad in ordner.iterdir():
if pfad.is_file():
dateien.append(pfad)
anzahl_ordner += 1
print("Ordner wird verarbeitet:")
print(ordner)
print(f"Präfix: {praefix}")
print()
protokoll.append(f"Verarbeiteter Ordner: {ordner}")
protokoll.append(f"Präfix: {praefix}")
except OSError as fehler:
meldung = (
"FEHLER: Ordnerinhalt konnte nicht gelesen werden:\n"
f'"{ordner}".\n'
f"Grund: {fehler}"
)
print(meldung)
print()
protokoll.append(meldung)
protokoll.append("")
anzahl_fehler += 1
continue
for datei in dateien:
if datei.name.casefold().startswith(praefix.casefold()):
meldung = (
"ÜBERSPRUNGEN:\n"
f'"{datei}"\n'
"- Präfix ist bereits am Anfang enthalten\n"
"---"
)
print(meldung)
protokoll.append(meldung)
anzahl_uebersprungen += 1
continue
neuer_name = praefix + datei.name
ziel_pfad = ordner / neuer_name
if ziel_pfad.exists():
meldung = (
"ÜBERSPRUNGEN:\n"
f'"{datei}"\n'
"- Zieldatei existiert bereits:\n"
f'"{ziel_pfad}"\n'
"---"
)
print(meldung)
protokoll.append(meldung)
anzahl_uebersprungen += 1
continue
plaene.append(
{
"ordner": ordner,
"praefix": praefix,
"quelle": datei,
"alter_name": datei.name,
"neuer_name": neuer_name,
"ziel": ziel_pfad,
}
)
protokoll.append("")
# ------------------------------------------------------------
# Sicherheitsabfrage bei der echten Ausführung
# ------------------------------------------------------------
if not testmodus and plaene:
print(
"ACHTUNG: Dieses Skript wird Dateien in den Unterordnern "
"wirklich umbenennen."
)
print()
antwort = input("Zum Fortfahren JA eingeben: ")
if antwort.upper() != "JA":
print()
print("Abgebrochen.")
print()
input("Drücke Enter zum Beenden")
sys.exit()
print()
# ------------------------------------------------------------
# Geplante Umbenennungen ausführen
# ------------------------------------------------------------
for plan in plaene:
if testmodus:
meldung = (
"WÜRDE UMBENENNEN:\n"
f'"{plan["quelle"]}"\n'
"zu\n"
f'"{plan["ziel"]}"\n'
"---"
)
print(meldung)
protokoll.append(meldung)
anzahl_umbenannt += 1
continue
try:
plan["quelle"].rename(plan["ziel"])
meldung = (
"UMBENANNT:\n"
f'"{plan["quelle"]}"\n'
"zu\n"
f'"{plan["ziel"]}"\n'
"---"
)
print(meldung)
protokoll.append(meldung)
anzahl_umbenannt += 1
except OSError as fehler:
meldung = (
"FEHLER:\n"
f'"{plan["quelle"]}"\n'
"konnte nicht umbenannt werden. Grund:\n"
f"{fehler}"
)
print(meldung)
protokoll.append(meldung)
anzahl_fehler += 1
# ------------------------------------------------------------
# Zusammenfassung
# ------------------------------------------------------------
protokoll.append("")
protokoll.append("Fertig.")
print()
print("Fertig.")
print()
meldung_ordner = f"Verarbeitete Unterordner: {anzahl_ordner}"
print(meldung_ordner)
protokoll.append(meldung_ordner)
if testmodus:
meldung_1 = f"Anzahl Dateien, die umbenannt würden: {anzahl_umbenannt}"
meldung_2 = f"Anzahl übersprungen: {anzahl_uebersprungen}"
meldung_3 = f"Anzahl Fehler: {anzahl_fehler}"
print(meldung_1)
print(meldung_2)
print(meldung_3)
print()
print("Es wurden keine Dateien umbenannt.")
print(
"Wenn alles richtig aussieht, entferne _test aus dem Namen "
"der Starter-Batchdatei."
)
protokoll.append(meldung_1)
protokoll.append(meldung_2)
protokoll.append(meldung_3)
protokoll.append("Es wurden keine Dateien umbenannt.")
else:
meldung_1 = f"Anzahl umbenannt: {anzahl_umbenannt}"
meldung_2 = f"Anzahl übersprungen: {anzahl_uebersprungen}"
meldung_3 = f"Anzahl Fehler: {anzahl_fehler}"
print(meldung_1)
print(meldung_2)
print(meldung_3)
protokoll.append(meldung_1)
protokoll.append(meldung_2)
protokoll.append(meldung_3)
# ------------------------------------------------------------
# Optionale Ausgabe als Logdatei und in die Zwischenablage
# ------------------------------------------------------------
protokoll_text = "\n".join(protokoll)
zeitstempel = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
logdatei = (
basis_ordner
/ f"umbenennprotokoll_unterordnerinhalt_{zeitstempel}.log"
)
if logdatei_erstellen:
try:
logdatei.write_text(protokoll_text, encoding="utf-8")
print()
print("Das Protokoll wurde erstellt:")
print(logdatei)
except OSError as fehler:
print()
print(
"FEHLER: Das Protokoll konnte nicht erstellt werden. "
f"Grund: {fehler}"
)
if zwischenablage_verwenden:
try:
subprocess.run(
"clip",
input=protokoll_text,
text=True,
encoding="utf-8",
check=True,
)
print()
print("Das Protokoll wurde zusätzlich in die Zwischenablage kopiert.")
except (OSError, subprocess.CalledProcessError) as fehler:
print()
print(
"FEHLER: Das Protokoll konnte nicht kopiert werden. "
f"Grund: {fehler}"
)
print()
input("Drücke Enter zum Beenden")
So funktioniert die erste Variante
Path.cwd() liefert den aktuellen Arbeitsordner als Path-Objekt:
basis_ordner = Path.cwd()
Die Starter-Batchdatei wechselt vorher mit cd /d "%~dp0" in ihren eigenen Ordner. Dadurch entspricht der aktuelle Arbeitsordner dem Ordner, in dem die Batch- und Python-Datei liegen.
iterdir() liefert die direkt enthaltenen Elemente. Mit is_dir() werden davon nur Ordner in die Liste unterordner aufgenommen:
unterordner = []
for pfad in basis_ordner.iterdir():
if pfad.is_dir():
unterordner.append(pfad)
Für jeden Unterordner wird anschließend ein eigenes Präfix gebildet. Ein weiterer Durchlauf mit iterdir() und is_file() übernimmt nur die unmittelbar darin liegenden Dateien. Tiefere Unterordner werden nicht durchsucht.
Die folgende Prüfung erkennt, ob das Präfix bereits am Anfang des Dateinamens steht:
if datei.name.casefold().startswith(praefix.casefold()):
casefold() vereinheitlicht beide Texte für einen Vergleich ohne Beachtung der Groß- und Kleinschreibung. startswith() prüft anschließend, ob der Dateiname mit dem Präfix beginnt.
exists() kontrolliert, ob der geplante Zielpfad bereits vorhanden ist. Ein bestehendes Ziel wird niemals überschrieben.
Jede gültige Umbenennung wird zuerst als Dictionary in plaene gespeichert:
plaene.append(
{
"quelle": datei,
"neuer_name": neuer_name,
"ziel": ziel_pfad,
}
)
Im Testmodus werden diese Pläne lediglich angezeigt. Im Echtmodus erfolgt zuerst die zusätzliche Bestätigung mit JA. Erst danach ruft die zweite Schleife rename() auf.
Starter-Batchdatei für Variante 1
@echo off
REM ============================================================
REM TOPTORIALS OFFICE - Python Grundkurs
REM Script: 006_unterordnerinhalt_mit_ordnername_umbenennen_starter_batch_test.bat
REM Beschreibung: Startet die Variante für Unterordnerinhalte.
REM Autor: Chris
REM YouTube: https://www.youtube.com/@TOPTORIALS-OFFICE
REM Webseite: https://www.toptorials.com
REM Version: 1.0
REM Stand: 2026-08-18
REM
REM Hinweis:
REM Solange _test im Dateinamen steht, wird --test uebergeben.
REM Fuer die echte Ausfuehrung _test aus dem Dateinamen entfernen.
REM ============================================================
chcp 65001 >nul
cd /d "%~dp0"
echo %~n0 | find /i "_test" >nul
if not errorlevel 1 (
py "006_unterordnerinhalt_mit_ordnername_umbenennen.py" --test
REM Alternative, falls py nicht funktioniert:
REM python "006_unterordnerinhalt_mit_ordnername_umbenennen.py" --test
) else (
py "006_unterordnerinhalt_mit_ordnername_umbenennen.py"
REM Alternative, falls py nicht funktioniert:
REM python "006_unterordnerinhalt_mit_ordnername_umbenennen.py"
)
%~dp0 liefert den Ordner der Starter-Batchdatei. cd /d wechselt in diesen Ordner, damit Python-Skript und zu verarbeitende Unterordner zuverlässig gefunden werden.
%~n0 liefert den Namen der gerade ausgeführten Batchdatei ohne Dateiendung. find /i "_test" prüft darin ohne Beachtung der Groß- und Kleinschreibung, ob der Testmodus verwendet werden soll.
py startet Python über den Python Launcher. Falls dieser Befehl nicht verfügbar ist, kann stattdessen die vorbereitete Alternative mit python aktiviert werden.
Variante 2: Ausgewählte Ordner über „Senden an“ verarbeiten
Die zweite Variante eignet sich für das Kontextmenü des Windows-Explorers. Dort können ein oder mehrere Ordner markiert und über Senden an an die Starter-Batchdatei übergeben werden.
Das Skript benennt nur die direkt enthaltenen Dateien der übergebenen Ordner um. Die ausgewählten Ordner selbst bleiben unverändert. Auch Unterordner und deren Inhalte werden nicht verarbeitet.
Vollständiges Python-Skript
# ============================================================
# TOPTORIALS OFFICE - Python Grundkurs
# Script: 006_sendto_ordnerinhalt_mit_ordnername_umbenennen.py
# Beschreibung: Benennt Dateien in über SendTo übergebenen Ordnern mit dem jeweiligen Ordnernamen als Präfix um.
# Autor: Chris
# YouTube: https://www.youtube.com/@TOPTORIALS-OFFICE
# Webseite: https://www.toptorials.com
# Version: 1.0
# Stand: 2026-08-18
# ============================================================
from datetime import datetime
from pathlib import Path
import subprocess
import sys
print()
argumente = sys.argv[1:]
testmodus = "--test" in argumente
# ------------------------------------------------------------
# Das Argument "--test" aus den übrigen Argumenten herausfiltern
# ------------------------------------------------------------
# Ausführlich geschrieben ist dieser Ablauf leichter verständlich.
argumente_ohne_test = []
for argument in argumente:
if argument != "--test":
argumente_ohne_test.append(argument)
argumente = argumente_ohne_test
# Die entsprechende Kurzschreibweise nennt man List Comprehension.
# argumente = [argument for argument in argumente if argument != "--test"]
# ------------------------------------------------------------
# Prüfen, ob mindestens ein Element übergeben wurde
# ------------------------------------------------------------
if not argumente:
print("Bitte sende mindestens einen Ordner an dieses Skript.")
print()
print("Du kannst einen oder mehrere Ordner im Explorer markieren,")
print("rechts anklicken und anschließend 'Senden an' verwenden.")
print()
input("Drücke Enter zum Beenden")
sys.exit()
# ------------------------------------------------------------
# Welche zusätzliche Ausgabe soll erstellt werden?
# Wichtig: Immer nur EINE der folgenden Varianten aktiv lassen.
# ------------------------------------------------------------
# Variante 1: Nur Bildschirmausgabe
logdatei_erstellen = False
zwischenablage_verwenden = False
# Variante 2: Logdatei erstellen
# logdatei_erstellen = True
# zwischenablage_verwenden = False
# Variante 3: Nur in die Zwischenablage kopieren
# logdatei_erstellen = False
# zwischenablage_verwenden = True
# Variante 4: Logdatei erstellen und in die Zwischenablage kopieren
# logdatei_erstellen = True
# zwischenablage_verwenden = True
# ------------------------------------------------------------
# Modus, Zähler und Protokoll vorbereiten
# ------------------------------------------------------------
if testmodus:
modus_text = "TESTMODUS"
else:
modus_text = "ECHTMODUS"
anzahl_umbenannt = 0
anzahl_uebersprungen = 0
anzahl_fehler = 0
anzahl_ordner = 0
protokoll = []
plaene = []
protokoll.append(
"Dateien in übergebenen Ordnern werden mit dem jeweiligen "
"Ordnernamen als Präfix umbenannt."
)
protokoll.append(f"Modus: {modus_text}")
protokoll.append("")
print(
"Dateien in übergebenen Ordnern werden mit dem jeweiligen "
"Ordnernamen als Präfix umbenannt..."
)
print()
print(f"Modus: {modus_text}")
print()
# ------------------------------------------------------------
# Doppelt übergebene Pfade entfernen
# ------------------------------------------------------------
eindeutige_argumente = []
bereits_vorhanden = set()
for element_pfad in argumente:
vergleichs_pfad = str(Path(element_pfad).absolute()).casefold()
if vergleichs_pfad not in bereits_vorhanden:
bereits_vorhanden.add(vergleichs_pfad)
eindeutige_argumente.append(element_pfad)
# ------------------------------------------------------------
# Übergebene Ordner und direkt enthaltene Dateien erfassen
# Unterordner werden nicht durchsucht.
# ------------------------------------------------------------
for element_pfad in eindeutige_argumente:
ordner = Path(element_pfad)
if not ordner.is_dir():
meldung = (
"ÜBERSPRUNGEN:\n"
f'"{element_pfad}"\n'
"- Der übergebene Pfad ist kein Ordner\n"
"---"
)
print(meldung)
protokoll.append(meldung)
anzahl_uebersprungen += 1
continue
try:
ordner = ordner.resolve()
if ordner.parent == ordner:
meldung = (
"ÜBERSPRUNGEN:\n"
f'"{ordner}"\n'
"- Eine Laufwerkswurzel wird aus Sicherheitsgründen "
"nicht verarbeitet\n"
"---"
)
print(meldung)
protokoll.append(meldung)
anzahl_uebersprungen += 1
continue
praefix = ordner.name + "_"
dateien = []
for pfad in ordner.iterdir():
if pfad.is_file():
dateien.append(pfad)
anzahl_ordner += 1
print("Ordner wird verarbeitet:")
print(ordner)
print(f"Präfix: {praefix}")
print()
protokoll.append(f"Verarbeiteter Ordner: {ordner}")
protokoll.append(f"Präfix: {praefix}")
except OSError as fehler:
meldung = (
"FEHLER: Ordnerinhalt konnte nicht gelesen werden:\n"
f'"{element_pfad}".\n'
f"Grund: {fehler}"
)
print(meldung)
protokoll.append(meldung)
anzahl_fehler += 1
continue
for datei in dateien:
if datei.name.casefold().startswith(praefix.casefold()):
meldung = (
"ÜBERSPRUNGEN:\n"
f'"{datei}"\n'
"- Präfix ist bereits am Anfang enthalten\n"
"---"
)
print(meldung)
protokoll.append(meldung)
anzahl_uebersprungen += 1
continue
neuer_name = praefix + datei.name
ziel_pfad = ordner / neuer_name
if ziel_pfad.exists():
meldung = (
"ÜBERSPRUNGEN:\n"
f'"{datei}"\n'
"- Zieldatei existiert bereits:\n"
f'"{ziel_pfad}"\n'
"---"
)
print(meldung)
protokoll.append(meldung)
anzahl_uebersprungen += 1
continue
plaene.append(
{
"ordner": ordner,
"praefix": praefix,
"quelle": datei,
"alter_name": datei.name,
"neuer_name": neuer_name,
"ziel": ziel_pfad,
}
)
protokoll.append("")
# ------------------------------------------------------------
# Sicherheitsabfrage bei der echten Ausführung
# ------------------------------------------------------------
if not testmodus and plaene:
print(
"ACHTUNG: Dieses Skript wird Dateien in den übergebenen "
"Ordnern wirklich umbenennen."
)
print()
antwort = input("Zum Fortfahren JA eingeben: ")
if antwort.upper() != "JA":
print()
print("Abgebrochen.")
print()
input("Drücke Enter zum Beenden")
sys.exit()
print()
# ------------------------------------------------------------
# Geplante Umbenennungen ausführen
# ------------------------------------------------------------
for plan in plaene:
if testmodus:
meldung = (
"WÜRDE UMBENENNEN:\n"
f'"{plan["quelle"]}"\n'
"zu\n"
f'"{plan["ziel"]}"\n'
"---"
)
print(meldung)
protokoll.append(meldung)
anzahl_umbenannt += 1
continue
try:
plan["quelle"].rename(plan["ziel"])
meldung = (
"UMBENANNT:\n"
f'"{plan["quelle"]}"\n'
"zu\n"
f'"{plan["ziel"]}"\n'
"---"
)
print(meldung)
protokoll.append(meldung)
anzahl_umbenannt += 1
except OSError as fehler:
meldung = (
"FEHLER:\n"
f'"{plan["quelle"]}"\n'
"konnte nicht umbenannt werden. Grund:\n"
f"{fehler}"
)
print(meldung)
protokoll.append(meldung)
anzahl_fehler += 1
# ------------------------------------------------------------
# Zusammenfassung
# ------------------------------------------------------------
protokoll.append("")
protokoll.append("Fertig.")
print()
print("Fertig.")
print()
meldung_ordner = f"Verarbeitete Ordner: {anzahl_ordner}"
print(meldung_ordner)
protokoll.append(meldung_ordner)
if testmodus:
meldung_1 = f"Anzahl Dateien, die umbenannt würden: {anzahl_umbenannt}"
meldung_2 = f"Anzahl übersprungen: {anzahl_uebersprungen}"
meldung_3 = f"Anzahl Fehler: {anzahl_fehler}"
print(meldung_1)
print(meldung_2)
print(meldung_3)
print()
print("Es wurden keine Dateien umbenannt.")
print(
"Wenn alles richtig aussieht, entferne _test aus dem Namen "
"der Starter-Batchdatei."
)
protokoll.append(meldung_1)
protokoll.append(meldung_2)
protokoll.append(meldung_3)
protokoll.append("Es wurden keine Dateien umbenannt.")
else:
meldung_1 = f"Anzahl umbenannt: {anzahl_umbenannt}"
meldung_2 = f"Anzahl übersprungen: {anzahl_uebersprungen}"
meldung_3 = f"Anzahl Fehler: {anzahl_fehler}"
print(meldung_1)
print(meldung_2)
print(meldung_3)
protokoll.append(meldung_1)
protokoll.append(meldung_2)
protokoll.append(meldung_3)
# ------------------------------------------------------------
# Optionale Ausgabe als Logdatei und in die Zwischenablage
# ------------------------------------------------------------
protokoll_text = "\n".join(protokoll)
zeitstempel = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
skript_ordner = Path(__file__).resolve().parent
logdatei = (
skript_ordner
/ f"umbenennprotokoll_sendto_ordnerinhalt_{zeitstempel}.log"
)
if logdatei_erstellen:
try:
logdatei.write_text(protokoll_text, encoding="utf-8")
print()
print("Das Protokoll wurde erstellt:")
print(logdatei)
except OSError as fehler:
print()
print(
"FEHLER: Das Protokoll konnte nicht erstellt werden. "
f"Grund: {fehler}"
)
if zwischenablage_verwenden:
try:
subprocess.run(
"clip",
input=protokoll_text,
text=True,
encoding="utf-8",
check=True,
)
print()
print("Das Protokoll wurde zusätzlich in die Zwischenablage kopiert.")
except (OSError, subprocess.CalledProcessError) as fehler:
print()
print(
"FEHLER: Das Protokoll konnte nicht kopiert werden. "
f"Grund: {fehler}"
)
print()
input("Drücke Enter zum Beenden")
So funktioniert die SendTo-Variante
sys.argv enthält die Argumente, mit denen Python gestartet wurde. Der Eintrag an Position null ist der Name des Python-Skripts. Mit sys.argv[1:] übernehmen wir deshalb nur die nachfolgenden Argumente:
argumente = sys.argv[1:]
Zu diesen Argumenten gehören der optionale Schalter --test und die vom Explorer übergebenen Ordnerpfade.
Der Testschalter wird mit einer ausführlich geschriebenen Schleife aus den übrigen Argumenten herausgefiltert:
argumente_ohne_test = []
for argument in argumente:
if argument != "--test":
argumente_ohne_test.append(argument)
argumente = argumente_ohne_test
Die entsprechende kurze Python-Schreibweise wird List Comprehension genannt und ist im Skript zusätzlich als Kommentar enthalten.
Doppelt übergebene Pfade werden mit einem Set erkannt. add() fügt Vergleichspfade zum Set hinzu, während append() die ursprünglichen Pfade in einer Liste sammelt.
eindeutige_argumente = []
bereits_vorhanden = set()
absolute() bildet einen absoluten Vergleichspfad. casefold() vereinheitlicht diesen Text für den Vergleich. Die Reihenfolge der zuerst übergebenen Ordner bleibt durch die zusätzliche Liste erhalten.
is_dir() sorgt dafür, dass nur Ordner verarbeitet werden. Einzelne Dateien werden mit einer verständlichen Meldung übersprungen. Nach resolve() schützt die Prüfung ordner.parent == ordner zusätzlich eine Laufwerkswurzel.
Für jeden gültigen Ordner wird dessen Name als Präfix verwendet. Die Planung, Prüfung mit exists(), Sicherheitsabfrage und Umbenennung funktionieren anschließend genauso wie bei der ersten Variante.
Starter-Batchdatei für die SendTo-Variante
@echo off
REM ============================================================
REM TOPTORIALS OFFICE - Python Grundkurs
REM Script: 006_sendto_ordnerinhalt_mit_ordnername_umbenennen_starter_batch_test.bat
REM Beschreibung: Startet die SendTo-Variante für Ordnerinhalte.
REM Autor: Chris
REM YouTube: https://www.youtube.com/@TOPTORIALS-OFFICE
REM Webseite: https://www.toptorials.com
REM Version: 1.0
REM Stand: 2026-08-18
REM
REM Hinweis:
REM Solange _test im Dateinamen steht, wird --test uebergeben.
REM Fuer die echte Ausfuehrung _test aus dem Dateinamen entfernen.
REM ============================================================
chcp 65001 >nul
cd /d "%~dp0"
echo %~n0 | find /i "_test" >nul
if not errorlevel 1 (
py "006_sendto_ordnerinhalt_mit_ordnername_umbenennen.py" --test %*
REM Alternative, falls py nicht funktioniert:
REM python "006_sendto_ordnerinhalt_mit_ordnername_umbenennen.py" --test %*
) else (
py "006_sendto_ordnerinhalt_mit_ordnername_umbenennen.py" %*
REM Alternative, falls py nicht funktioniert:
REM python "006_sendto_ordnerinhalt_mit_ordnername_umbenennen.py" %*
)
%* steht für alle Argumente, die an die Batchdatei übergeben wurden. Über SendTo sind das die vollständigen Pfade sämtlicher im Explorer ausgewählter Ordner.
SendTo-Verknüpfung einrichten
Für die SendTo-Variante wird eine Verknüpfung zur zugehörigen Starter-Batchdatei angelegt:
- Die Starter-Batchdatei im Kursordner mit der rechten Maustaste anklicken.
- Verknüpfung erstellen auswählen.
- Die Verknüpfung verständlich benennen, zum Beispiel
Python 006 - Ordnerinhalt mit Ordnername umbenennen TEST. - Mit
Windows-Taste + Rdas Fenster Ausführen öffnen. shell:sendtoeingeben und mit Enter bestätigen.- Die Verknüpfung in den geöffneten SendTo-Ordner verschieben.
Solange _test im Namen der tatsächlichen Starter-Batchdatei steht, wird der Testmodus verwendet. Entscheidend ist nicht der Name der Verknüpfung, sondern der Name der Batchdatei, auf die sie verweist.
Logdateien und Zwischenablage
Die Liste protokoll sammelt alle wichtigen Meldungen. Anschließend verbindet:
protokoll_text = "\n".join(protokoll)
alle Listeneinträge mit Zeilenumbrüchen zu einem zusammenhängenden Text.
Die Logdatei wird mit UTF-8 gespeichert:
logdatei.write_text(protokoll_text, encoding="utf-8")
Für die Windows-Zwischenablage startet subprocess.run() das Programm clip und übergibt den Protokolltext über die Standardeingabe.
Bei Variante 1 wird eine aktivierte Logdatei im aktuellen Hauptordner gespeichert. Bei der SendTo-Variante wird sie im Ordner des Python-Skripts abgelegt. __file__ liefert dafür den Pfad der gerade ausgeführten Python-Datei.
Typische Meldungen
WÜRDE UMBENENNEN
Der Testmodus zeigt eine geplante Umbenennung an. Es wurde nichts verändert.
UMBENANNT
Die Umbenennung wurde im Echtmodus erfolgreich ausgeführt.
ÜBERSPRUNGEN
Die Datei oder der übergebene Pfad wurde absichtlich nicht verändert, zum Beispiel wegen eines vorhandenen Präfixes, eines bestehenden Zielpfades oder eines ungeeigneten Übergabetyps.
FEHLER
Bei einer Datei- oder Ordneroperation ist eine Ausnahme aufgetreten. Der konkrete Grund wird zusammen mit der Meldung ausgegeben.
Typische Fehler und Lösungen
Python oder der Python Launcher wurde nicht gefunden
Prüfe mit py --version und python --version, welcher Startbefehl verfügbar ist. Falls py nicht funktioniert, kann in der Starter-Batchdatei die vorbereitete Alternative mit python aktiviert werden.
Die Python-Datei wurde nicht gefunden
Python-Datei und Starter-Batchdatei müssen im gleichen Variantenordner liegen. Außerdem muss der im Batchcode verwendete Dateiname exakt stimmen.
Die SendTo-Datei wurde direkt gestartet
Die SendTo-Variante benötigt mindestens einen übergebenen Ordnerpfad. Verwende sie über eine Verknüpfung im Menü Senden an.
Eine übergebene Datei wurde übersprungen
Das ist beabsichtigt. Diese SendTo-Variante akzeptiert ausschließlich Ordner. Die ausgewählten Ordner selbst werden nicht umbenannt.
Dateien in tieferen Unterordnern wurden nicht umbenannt
Das ist beabsichtigt. iterdir() erfasst nur die direkten Elemente der jeweiligen Ordnerebene. Das Skript arbeitet nicht rekursiv.
Eine Datei wurde wegen eines vorhandenen Ziels übersprungen
Im gleichen Ordner existiert bereits eine Datei mit dem geplanten neuen Namen. Das Skript überschreibt dieses Ziel nicht.
Keine Logdatei wurde erstellt
In der Standardkonfiguration sind Logdatei und Zwischenablage ausgeschaltet. Aktiviere die gewünschte Ausgabevariante über die beiden Wahrheitswerte.
Die Eingabe ja wurde trotzdem nicht akzeptiert
Das Skript verwendet antwort.upper() != "JA". Dadurch werden JA, Ja und ja akzeptiert. Zusätzliche Leerzeichen werden jedoch nicht automatisch entfernt.
Umlaute oder Sonderzeichen werden falsch angezeigt
Speichere Python- und Batchdateien als UTF-8. Die Starter-Batchdateien stellen die Windows-Konsole zusätzlich mit chcp 65001 auf die UTF-8-Codepage um.
Nützliche Python-Begriffe aus diesem Teil
Path.cwd()
Liefert den aktuellen Arbeitsordner als Path-Objekt.
Path.iterdir()
Liefert die direkt enthaltenen Elemente eines Ordners.
is_dir() und is_file()
Prüfen, ob ein Pfad ein Ordner oder eine Datei ist.
Path.name
Liefert den letzten Namensteil eines Pfades.
casefold()
Vereinheitlicht Texte für Vergleiche ohne Beachtung der Groß- und Kleinschreibung.
startswith()
Prüft, ob ein Text mit einem bestimmten Text beginnt.
exists()
Prüft, ob ein Pfad bereits vorhanden ist.
rename()
Benennt eine Datei um oder verschiebt sie zu einem anderen Pfad.
sys.argv
Enthält die Startargumente des Python-Programms.
Liste
Speichert mehrere Werte in einer festen Reihenfolge.
Set
Speichert eindeutige Werte und eignet sich für Duplikatprüfungen.
Dictionary
Speichert zusammengehörige Werte unter benannten Schlüsseln.
List Comprehension
Ist eine kompakte Python-Schreibweise zum Erzeugen oder Filtern einer Liste.
__file__
Enthält den Pfad der gerade ausgeführten Python-Datei.
try und except
Fangen erwartbare Fehler kontrolliert ab.
Zusammenfassung
- Der Name jedes verarbeiteten Ordners wird automatisch als Präfix verwendet.
- Das Präfix endet mit einem Unterstrich.
- Nur direkt enthaltene Dateien werden verarbeitet.
- Die Ordner selbst und mögliche Unterordner bleiben unverändert.
- Bereits vorhandene Präfixe werden ohne Beachtung der Groß- und Kleinschreibung erkannt.
- Vorhandene Zielpfade werden nicht überschrieben.
- Alle gültigen Umbenennungen werden zuerst als Pläne gespeichert.
- Der Testmodus zeigt die geplanten Änderungen ohne Umbenennung an.
- Der Echtmodus verlangt zusätzlich die Bestätigung mit
JA. - Die SendTo-Variante kann einen oder mehrere ausgewählte Ordner verarbeiten.
- Logdatei und Zwischenablage lassen sich bei Bedarf aktivieren.
Damit lassen sich zusammengehörige Dateien eindeutig ihrem Ordner zuordnen, ohne jeden Dateinamen einzeln bearbeiten zu müssen.
Video zu diesem Tutorial:
Das könnte Dich auch interessieren
Keine Einträge gefunden

