============================================================
TOPTORIALS OFFICE - Python Grundkurs
Teil 008: Text in Dateinamen ersetzen
============================================================

Autor: Chris
Webseite: https://www.toptorials.com
YouTube: https://www.youtube.com/@TOPTORIALS-OFFICE
Skriptversion: Grundkurs 1.0
Stand dieser Anleitung: 01.09.2026


WICHTIG VOR DEM ERSTEN START
============================================================

Bitte zuerst mit Kopien unwichtiger Dateien arbeiten.

Für den Testmodus muss _test im tatsächlichen Dateinamen der
Starter-Batchdatei stehen. Der Hinweis im Kommentar der Datei
oder der Anzeigename einer Verknüpfung genügt dafür nicht.

Vor der Eingabe des Suchtextes muss im Fenster stehen:

Testmodus: JA

Ohne _test wird der Echtmodus gestartet. Die tatsächliche
Umbenennung erfolgt dann erst nach der Bestätigung mit JA.

Die Ersetzung betrifft den vollständigen Dateinamen und damit
auch die Dateiendung. Eine geänderte Endung wandelt den Inhalt
der Datei NICHT in ein anderes Dateiformat um.

Diese Skripte erstellen keine Sicherung und besitzen keine
automatische Rückgängig-Funktion.


INHALT
============================================================

01. Worum geht es?
02. Voraussetzungen
03. Ordner und Dateien
04. Schnellstart: einfache Variante
05. SendTo-Variante einrichten und verwenden
06. Testmodus und Echtmodus
07. Suchtext und Ersatztext
08. Namenskonflikte und automatische Nummerierung
09. Welche Dateien werden verarbeitet?
10. Ablauf und Bildschirmausgabe
11. Aufgaben der Starter-Batchdateien
12. Direkter Aufruf mit Python
13. Häufige Fragen und Fehler
14. Grenzen und Sicherheit
15. Kurze Zusammenfassung


01. WORUM GEHT ES?
============================================================

Mit diesen Skripten könnt ihr einen Text in mehreren Dateinamen
ersetzen oder entfernen.

Beispiel:

Datei:       MeinBeispiel.txt
Suchtext:    Mein
Ersatztext:  Dein
Ergebnis:    DeinBeispiel.txt

Wenn ihr beim Ersatztext nur Enter drückt, wird der Suchtext
entfernt:

Datei:       MeinBeispiel.txt
Suchtext:    Mein
Ersatztext:  leer lassen
Ergebnis:    Beispiel.txt

Diese Ergebnisse setzen voraus, dass der gewünschte Zielname
noch frei ist. Bei Namenskonflikten wird eine Nummer ergänzt.

Es gibt zwei Varianten:

- 01_Einfach:
  Bearbeitet beim Start über die Batchdatei die Dateien im
  Ordner dieser Starter-Batchdatei.

- 02_SendTo_Text_ersetzen:
  Bearbeitet ausgewählte Dateien sowie die direkt enthaltenen
  Dateien ausgewählter Ordner über das Menü "Senden an".

Beide Varianten arbeiten ohne rekursive Ordnersuche.
Die Dateien bleiben in ihren jeweiligen Ordnern.
Ordnernamen und Dateiinhalte werden nicht verändert.


02. VORAUSSETZUNGEN
============================================================

- Windows für die Starter-Batchdateien und das SendTo-Menü.
- Eine installierte Version von Python 3.
- Der Python Launcher py oder alternativ der Befehl python.
- Ausreichende Rechte zum Umbenennen der betroffenen Dateien.
- Python-Skript und passender Starter liegen jeweils gemeinsam
  in einem Ordner.

Mit diesen Befehlen könnt ihr die Installation prüfen:

py --version

oder:

python --version

Die Skripte verwenden ausschließlich Module aus der
Python-Standardbibliothek. Es müssen keine zusätzlichen Pakete
mit pip installiert werden.

Verwendete Module:

pathlib
re
sys

Startet die Skripte für die normalen Übungen über die
mitgelieferten Starter-Batchdateien.


03. ORDNER UND DATEIEN
============================================================

Der vorgesehene Hauptordner lautet:

C:\TOPTORIALS_CODE\020_Python_Grundkurs\008_Text_in_Dateinamen_ersetzen

Diese README.txt liegt im Hauptordner des Kurspakets.


Variante 1: einfacher Ordnerbetrieb
------------------------------------------------------------

Unterordner:

01_Einfach

Python-Datei:

008_text_in_dateinamen_ersetzen.py

Starter für den Testmodus:

008_text_in_dateinamen_ersetzen_starter_batch_test.bat

Startername für den Echtmodus:

008_text_in_dateinamen_ersetzen_starter_batch.bat


Variante 2: SendTo
------------------------------------------------------------

Unterordner:

02_SendTo_Text_ersetzen

Python-Datei:

008_sendto_text_in_dateinamen_ersetzen.py

Starter für den Testmodus:

008_sendto_text_in_dateinamen_ersetzen_starter_batch_test.bat

Startername für den Echtmodus:

008_sendto_text_in_dateinamen_ersetzen_starter_batch.bat


Hinweise zu den Dateinamen
------------------------------------------------------------

Die beiden genannten Starternamen pro Variante bezeichnen
denselben Starter vor beziehungsweise nach dem Umbenennen.
Es werden nicht zwingend zwei separate Starter benötigt.

Wenn ein Starter bereits ohne _test vorliegt, ergänzt diesen
Zusatz vor dem ersten Probelauf.

Die Python-Dateinamen müssen exakt zu den Namen passen, die im
jeweiligen Starter hinter py stehen.

Zusätze wie (1) oder (2), die beispielsweise beim erneuten
Herunterladen entstehen können, gehören nicht zu den oben
genannten Skriptnamen.


04. SCHNELLSTART: EINFACHE VARIANTE
============================================================

1. Legt einen Ordner mit Kopien unwichtiger Testdateien an.

2. Kopiert nur das Python-Skript der einfachen Variante und
   seinen Starter gemeinsam in diesen Testordner.

3. Prüft den Namen der Starter-Batchdatei. Für den Testlauf:

   008_text_in_dateinamen_ersetzen_starter_batch_test.bat

4. Startet diese Batchdatei per Doppelklick.

5. Prüft die Anzeige:

   Testmodus: JA

6. Gebt den Suchtext ein, beispielsweise:

   Mein

7. Gebt den Ersatztext ein, beispielsweise:

   Dein

   Zum Entfernen des Suchtextes lasst die zweite Eingabe leer
   und drückt nur Enter.

8. Prüft die ausgegebenen Zeilen QUELLE und ZIEL.

9. Im Testmodus werden keine Dateien umbenannt.
   Die Batchdatei wartet anschließend auf einen Tastendruck.

10. Wenn die Vorschau stimmt, entfernt _test aus dem Namen
    der Starter-Batchdatei.

11. Startet den Starter erneut und gebt die gewünschten
    Such- und Ersatztexte erneut ein.

12. Kontrolliert die neue Vorschau. Bestätigt den Echtlauf
    nur bei korrekten Zielen mit JA.

Wichtig:

Die einfache Variante bearbeitet den Ordner des Starters,
nicht automatisch einen anderen gerade geöffneten
Explorer-Ordner.

Die README.txt ist eine normale Textdatei und nicht von der
Verarbeitung ausgeschlossen. Lasst sie deshalb im Hauptordner
des Kurspakets und kopiert sie nicht mit in den zu bearbeitenden
Testordner.


05. SENDTO-VARIANTE EINRICHTEN UND VERWENDEN
============================================================

Bei SendTo bleiben Python-Skript und Starter gemeinsam an ihrem
festen Speicherort:

C:\TOPTORIALS_CODE\020_Python_Grundkurs\008_Text_in_Dateinamen_ersetzen\02_SendTo_Text_ersetzen


Verknüpfung einrichten
------------------------------------------------------------

1. Prüft, dass der Original-Starter für den Probelauf so heißt:

   008_sendto_text_in_dateinamen_ersetzen_starter_batch_test.bat

2. Drückt Windows + R.

3. Gebt Folgendes ein:

   shell:sendto

4. Bestätigt mit Enter.

5. Legt in dem geöffneten Ordner eine Verknüpfung zur
   Starter-Batchdatei an.

6. Gebt der Verknüpfung einen verständlichen Namen, etwa:

   Text in Dateinamen ersetzen - TEST


SendTo verwenden
------------------------------------------------------------

1. Markiert im Windows-Explorer die gewünschten Dateien
   und/oder Ordner.

2. Wählt im Kontextmenü "Senden an" und anschließend eure
   eingerichtete Verknüpfung.

3. Prüft im Fenster die Anzeige "Testmodus: JA".

4. Gebt Suchtext und Ersatztext ein.

5. Kontrolliert die geplanten Änderungen.

Bei einer direkt übergebenen Datei wird diese Datei geprüft.
Bei einem übergebenen Ordner werden dessen direkt enthaltene
Dateien erfasst. Tiefere Unterordner bleiben unberücksichtigt.

Wenn dieselbe Datei direkt und gleichzeitig über ihren Ordner
erfasst wurde, wird sie nur einmal verarbeitet.


Auf Echtmodus umstellen
------------------------------------------------------------

Entfernt _test aus dem Namen der ORIGINAL-Starter-Batchdatei.

Prüft anschließend das Ziel der SendTo-Verknüpfung.
Aktualisiert oder erstellt die Verknüpfung bei Bedarf neu,
damit sie auf den umbenannten Starter zeigt.

Der Name der Verknüpfung allein steuert den Testmodus NICHT.

Nach dem erneuten Aufruf erscheint "Testmodus: NEIN".
Die tatsächliche Umbenennung muss zusätzlich mit JA bestätigt
werden.


06. TESTMODUS UND ECHTMODUS
============================================================

Testmodus:
------------------------------------------------------------

- _test steht im Namen des Starters.
- Der Starter übergibt --test an Python.
- Das Skript zeigt "Testmodus: JA".
- Suchtext und Ersatztext werden abgefragt.
- Die Umbenennungen werden geplant und angezeigt.
- Es werden keine Dateien umbenannt.


Echtmodus:
------------------------------------------------------------

- _test fehlt im Namen des Starters.
- Der Starter übergibt kein --test.
- Das Skript zeigt "Testmodus: NEIN".
- Suchtext und Ersatztext werden abgefragt.
- Die Umbenennungen werden geplant und angezeigt.
- Bei mindestens einem Plan erscheint die Sicherheitsabfrage.
- Erst nach der Eingabe JA werden die Pläne ausgeführt.

Bei der Bestätigung wird Groß- und Kleinschreibung ignoriert.
Leerzeichen am Anfang und Ende werden mit strip() entfernt.
Eine andere Antwort bricht vor der Umbenennung ab.

Die Vorschau wird nicht für einen späteren Start gespeichert.
Beim erneuten Aufruf entstehen aus den dann vorhandenen Dateien
neue Pläne. Deshalb auch die Vorschau des Echtlaufs prüfen.


07. SUCHTEXT UND ERSATZTEXT
============================================================

Alle passenden Vorkommen
------------------------------------------------------------

Es werden alle Vorkommen des Suchtextes ersetzt, nicht nur die
erste Fundstelle oder der Anfang des Dateinamens.

Datei:       Alt_alt_Bericht.txt
Suchtext:    alt
Ersatztext:  Neu
Ergebnis:    Neu_Neu_Bericht.txt


Groß- und Kleinschreibung
------------------------------------------------------------

Die Suche ignoriert Groß- und Kleinschreibung.
Der Ersatztext wird in der eingegebenen Schreibweise verwendet.

Die entscheidende Vorbereitung lautet:

suchmuster = re.compile(re.escape(alter_text), re.IGNORECASE)

re.escape() maskiert Zeichen, die in einem regulären Ausdruck
normalerweise eine besondere Bedeutung besitzen. Dadurch wird
der eingegebene Suchtext wörtlich gesucht.


Ersatztext wörtlich einsetzen
------------------------------------------------------------

Die Ersetzung verwendet:

suchmuster.sub(lambda _: neuer_text, datei.name)

Die lambda-Funktion gibt bei jedem Treffer genau den eingegebenen
Ersatztext zurück. Dadurch werden besondere Zeichen im Ersatztext
nicht als Regex-Ersatzanweisung ausgewertet.


Leere Eingaben
------------------------------------------------------------

Leerer Suchtext:
Der Durchlauf wird abgebrochen.

Leerer Ersatztext:
Der gefundene Suchtext wird entfernt.

Zum Entfernen keine Anführungszeichen eingeben.
Drückt bei der zweiten Frage einfach Enter.

Ein tatsächlich eingegebenes Leerzeichen ist nicht leer.
Suchtext und Ersatztext werden nicht automatisch getrimmt.


Die Dateiendung gehört zum Namen
------------------------------------------------------------

Datei:       Bericht.TXT
Suchtext:    .txt
Ersatztext:  .md
Ergebnis:    Bericht.md

Der Inhalt wird dabei nicht konvertiert.
Ändert Dateiendungen nur, wenn ihr die Folgen kennt.


Leerer Basisname
------------------------------------------------------------

Das Skript prüft zusätzlich den Namen ohne die letzte Endung.
Wird dieser Basisname vollständig entfernt, verwendet es:

Unbenannt + ursprüngliche Dateiendung

Beispiel:

Datei:       Beispiel.txt
Suchtext:    Beispiel
Ersatztext:  leer lassen
Ergebnis:    Unbenannt.txt


Ungültige Zeichen
------------------------------------------------------------

Der Ersatztext wird auf Zeichen geprüft, die unter Windows in
Dateinamen nicht erlaubt sind. Dazu gehören unter anderem:

< > : " / \ | ? *

Ein ungültiger Ersatztext beendet den Durchlauf, bevor Pläne
erstellt oder Dateien verändert werden.


08. NAMENSKONFLIKTE UND AUTOMATISCHE NUMMERIERUNG
============================================================

Ist ein gewünschter Zielname bereits vorhanden, ergänzt die
Funktion get_freier_zielpfad() eine dreistellige Nummer vor der
letzten Dateiendung.

Beispiel:

MeinBeispiel.txt
Beispiel.txt

Suchtext: Mein
Ersatztext: leer lassen

Ergebnis für MeinBeispiel.txt:

Beispiel_001.txt

Ist auch dieser Name belegt, wird weitergesucht:

Beispiel_002.txt
Beispiel_003.txt
und so weiter


Sonderfall beim Entfernen von _001
------------------------------------------------------------

Vorhandene Dateien:

Unbenannt.txt
Unbenannt_001.txt

Suchtext:

_001

Ersatztext:

leer lassen

Unbenannt.txt ist bereits belegt. Unbenannt_001.txt ist während
der Planung noch die Quelldatei und kann nicht als neu gesuchter
Nummernkandidat verwendet werden.

Das nächste freie Ziel lautet daher:

Unbenannt_002.txt


Vorhandene und geplante Ziele
------------------------------------------------------------

zielpfad.exists() prüft, ob der Zielpfad bereits im Dateisystem
vorhanden ist.

Das Set reservierte_ziele speichert zusätzlich Zielpfade, die
während dieses Durchlaufs schon für andere Pläne vorgesehen sind.

Damit erhalten nicht zwei Dateien denselben geplanten Zielpfad.

Die Pfade werden mit absolute() und casefold() in einen
Vergleichswert umgewandelt. Die tatsächliche Schreibweise des
gespeicherten Dateinamens wird dadurch nicht verändert.


09. WELCHE DATEIEN WERDEN VERARBEITET?
============================================================

Verarbeitet werden normale Dateien, deren Dateiname den Suchtext
enthält und deren ursprüngliche Endung nicht ausgeschlossen ist.

Ausgeschlossene Endungen:

.bat
.cmd
.ps1
.py
.log

Die Prüfung der Endung ignoriert Groß- und Kleinschreibung.

Dadurch werden die Starter-Batchdateien und Python-Skripte nicht
selbst umbenannt.

Dateien ohne Treffer werden mit "keine Änderung" übersprungen.

Die einfache Variante verarbeitet die direkt enthaltenen Dateien
im aktuellen Arbeitsordner.

Die SendTo-Variante verarbeitet direkt übergebene Dateien und die
direkt enthaltenen Dateien übergebener Ordner.

Tiefere Unterordner werden nicht durchsucht.
Ordnernamen werden nicht umbenannt.

Versteckte Dateien können von pathlib ebenfalls erfasst werden,
sofern Python auf sie zugreifen darf und sie nicht aufgrund ihrer
Endung ausgeschlossen sind.


10. ABLAUF UND BILDSCHIRMAUSGABE
============================================================

Die Skripte arbeiten in mehreren Schritten:

1. Testmodus bestimmen.
2. Suchtext und Ersatztext abfragen.
3. Ersatztext auf ungültige Zeichen prüfen.
4. Suchmuster vorbereiten.
5. Dateien erfassen und sortieren.
6. Ausschlüsse und unveränderte Namen erkennen.
7. Freie Zielpfade bestimmen und reservieren.
8. Alle gültigen Umbenennungen als Dictionaries planen.
9. QUELLE und ZIEL jedes Plans anzeigen.
10. Im Echtmodus die Bestätigung JA abfragen.
11. Die gespeicherten Pläne mit rename() ausführen.
12. Anzahl umbenannter, übersprungener und fehlerhafter Dateien
    ausgeben.

Beispiel einer Vorschau:

QUELLE: C:\Test\MeinBeispiel.txt
ZIEL:   C:\Test\Beispiel_001.txt

Im Testmodus folgt unter anderem:

Es wurde nichts umbenannt.

Im Echtmodus erscheint nach einer erfolgreichen Umbenennung:

UMBENANNT: C:\Test\MeinBeispiel.txt -> C:\Test\Beispiel_001.txt


11. AUFGABEN DER STARTER-BATCHDATEIEN
============================================================

Die Starter übernehmen folgende Aufgaben:

- Konsolencodepage mit chcp 65001 auf UTF-8 einstellen.
- Mit cd /d "%~dp0" in den eigenen Ordner wechseln.
- Den eigenen Dateinamen mit %~n0 ermitteln.
- Mit find /i nach _test suchen.
- Python über den Launcher py starten.
- Im Testzweig --test übergeben.
- Bei SendTo mit %* alle übergebenen Pfade weiterreichen.
- Mit pause das Konsolenfenster offen halten.

Die öffnende Klammer in:

echo("%~n0"

gehört zur sicheren echo-Schreibweise von cmd.exe. Sie wird nicht
als normale Programmierklammer geöffnet und benötigt deshalb kein
schließendes Gegenstück.

Wenn der Python Launcher py nicht funktioniert, stehen in den
Startern alternative Aufrufe mit python als Kommentare bereit.
Aktiviert dann die passende Alternative und deaktiviert den
bisherigen py-Aufruf.


12. DIREKTER AUFRUF MIT PYTHON
============================================================

Normalerweise werden die mitgelieferten Starter verwendet.
Die Skripte können aber auch in einer Eingabeaufforderung oder
einem Terminal direkt gestartet werden.


Einfache Variante im Testmodus:
------------------------------------------------------------

py "008_text_in_dateinamen_ersetzen.py" --test


Einfache Variante im Echtmodus:
------------------------------------------------------------

py "008_text_in_dateinamen_ersetzen.py"


SendTo-Skript mit einer Datei im Testmodus:
------------------------------------------------------------

py "008_sendto_text_in_dateinamen_ersetzen.py" --test "C:\Test\MeinBeispiel.txt"


SendTo-Skript mit mehreren Pfaden im Testmodus:
------------------------------------------------------------

py "008_sendto_text_in_dateinamen_ersetzen.py" --test "C:\Test\Datei.txt" "C:\Test\Ordner"

Pfade mit Leerzeichen müssen in Anführungszeichen stehen.


13. HÄUFIGE FRAGEN UND FEHLER
============================================================

Der Befehl py wurde nicht gefunden
------------------------------------------------------------

Prüft mit py --version, ob der Python Launcher verfügbar ist.
Verwendet bei Bedarf die vorbereitete Alternative mit python.


Das Python-Skript wurde nicht gefunden
------------------------------------------------------------

Prüft, ob Python-Skript und Starter gemeinsam im vorgesehenen
Ordner liegen und die Dateinamen exakt stimmen.


Testmodus: NEIN erscheint unerwartet
------------------------------------------------------------

Im tatsächlichen Namen des Original-Starters fehlt _test.
Eine Kommentarzeile oder der Name der Verknüpfung genügt nicht.


Der Suchtext wird nicht gefunden
------------------------------------------------------------

Prüft die Eingabe und den vollständigen Dateinamen. Die Suche
ignoriert Groß- und Kleinschreibung, aber Leerzeichen und andere
Zeichen gehören zum Suchtext.


Nach dem Entfernen von _001 erscheint _002
------------------------------------------------------------

Der Name ohne Nummer ist bereits belegt. Die Quelldatei mit _001
ist während der Planung ebenfalls noch vorhanden. Das Skript
sucht deshalb den nächsten freien Namen.


Es werden weniger Dateien verarbeitet als erwartet
------------------------------------------------------------

Prüft die ausgeschlossenen Endungen, die Lage der Dateien und den
Suchtext. Unterordner werden nicht rekursiv durchsucht. Doppelt
erfasste SendTo-Dateien werden nur einmal verarbeitet.


Eine Datei kann nicht umbenannt werden
------------------------------------------------------------

Mögliche Ursachen:

- fehlende Schreibrechte
- Datei wird von einem anderen Programm gesperrt
- Zielpfad wurde nach der Planung anderweitig belegt
- reservierter Windows-Dateiname
- zu langer Pfad oder Dateiname
- nicht mehr vorhandene Quelldatei

Der Fehler wird ausgegeben. Anschließend versucht das Skript, die
weiteren Pläne zu verarbeiten.


14. GRENZEN UND SICHERHEIT
============================================================

- Die Skripte besitzen keine automatische Rückgängig-Funktion.
- Es wird keine Sicherungskopie erstellt.
- Eine Testvorschau garantiert nicht, dass die spätere
  Umbenennung erfolgreich sein wird.
- Zwischen Planung und Ausführung kann sich das Dateisystem
  verändern.
- Die Grundkurs-Version prüft nicht sämtliche Windows-Regeln für
  Dateinamen im Voraus.
- Ordnernamen werden nicht verändert.
- Tiefere Unterordner werden nicht durchsucht.
- Dateiinhalte werden nicht konvertiert.
- Eine geänderte Dateiendung ändert nur den Namen.
- Logdatei und Zwischenablageausgabe sind in dieser schlanken
  Grundkurs-Version nicht enthalten.

Empfohlener Testablauf:

1. Kopien unwichtiger Dateien verwenden.
2. _test im Namen des Original-Starters kontrollieren.
3. Im Fenster "Testmodus: JA" prüfen.
4. Alle Zeilen QUELLE und ZIEL kontrollieren.
5. Für wichtige Daten eine aktuelle Sicherung anlegen.
6. Erst danach den Echtmodus verwenden.
7. Auch dessen Vorschau noch einmal prüfen.
8. Nur bei korrekten Zielen mit JA bestätigen.

Die Nutzung der Skripte erfolgt auf eigene Verantwortung.


15. KURZE ZUSAMMENFASSUNG
============================================================

- input() liest Suchtext, Ersatztext und Bestätigung ein.
- re.escape() behandelt den Suchtext wörtlich.
- re.IGNORECASE ignoriert Groß- und Kleinschreibung.
- sub() ersetzt alle Treffer.
- Eine lambda-Funktion gibt den Ersatztext wörtlich zurück.
- Ein leerer Ersatztext entfernt den Suchtext.
- Path verarbeitet Dateien, Ordner, Namen und Endungen.
- Ein leerer Basisname wird durch Unbenannt ersetzt.
- get_freier_zielpfad() ergänzt bei Konflikten _001, _002 usw.
- Ein Set reserviert bereits geplante Zielpfade.
- Die SendTo-Variante verhindert doppelte Quelldateien.
- Listen mit Dictionaries speichern Quelle und Ziel.
- Der Testmodus zeigt die Pläne an, verändert aber keine Dateien.
- Im Echtmodus führt rename() die Pläne nach JA aus.
- Die Starter aktivieren den Testmodus über _test im Dateinamen.


============================================================
TOPTORIALS OFFICE
============================================================

Webseite:
https://www.toptorials.com

YouTube:
https://www.youtube.com/@TOPTORIALS-OFFICE

Die fertigen Skripte, weitere Erklärungen und die Testumgebung
findet ihr auf der Webseite.
