Toptorials Tutorials WeblogoLogobild kleinLogobild kleinToptorials Tutorials Weblogo
  • ALLE THEMEN IM ÜBERBLICK
  • YouTube
  • INFOS
    • SITEMAP
    • ÜBER TOPTORIALS
✕
            No results See all results

            Python Grundkurs Teil 010: Zwei Ordner vergleichen und fehlende Dateien finden

            • Startseite
            • Tutorials Windows Automatisierung Python Grundkurs
            • Python Grundkurs Teil 010: Zwei Ordner vergleichen und fehlende Dateien finden

            Python Grundkurs Teil 010: Zwei Ordner vergleichen und fehlende Dateien finden

            Worum geht es in diesem Teil?

            Welche Dateien fehlen im anderen Ordner? In diesem Teil vergleichen wir die Dateinamen aus zwei Ordnern in beide Richtungen. Ihr entscheidet dabei, ob die Dateiendung berücksichtigt wird oder ob nur der Name vor der letzten Endung zählt. Das ist beispielsweise praktisch, wenn ihr Originalbilder mit exportierten Bildern oder Word-Dokumente mit PDF-Dateien abgleichen möchtet.

            Wir erstellen wieder zwei Varianten: einen Vergleich mit fest eingetragenen Ordnern und eine SendTo-Version für zwei im Windows-Explorer ausgewählte Ordner. Die Ergebnisse erscheinen im Fenster und werden im Echtmodus zusätzlich als Textdateien gespeichert.

            Was ist das Ziel?

            Ihr erhaltet zwei Listen: Namen aus Ordner 2, die in Ordner 1 fehlen, und Namen aus Ordner 1, die in Ordner 2 fehlen. Vorhandene Projektdateien werden dabei weder umbenannt noch kopiert, verschoben oder gelöscht.

            Ein Namensvergleich ist kein Inhaltsvergleich.

            Gleiche Namen bedeuten nicht, dass Dateien denselben Inhalt besitzen. Das Skript prüft weder Dateigrößen noch Änderungszeiten oder Prüfsummen. Unterordner werden nicht durchsucht und fehlende Ordner werden nicht ermittelt.

            Warum verwenden wir diesmal mehrere Funktionen?

            Zum Abschluss des Grundkurses organisieren wir einzelne Aufgaben in Funktionen. Dadurch bekommt jede Aufgabe einen eigenen Namen: Dateien einlesen, Vergleichsnamen sammeln, Berichte erstellen und Berichte speichern. Wiederkehrende Abläufe müssen wir so innerhalb eines Skripts nur einmal schreiben.

            Bei kleinen Skripten können Anweisungen direkt untereinander stehen. Wenn ein Programm wächst, helfen Funktionen dabei, Aufgaben zu überblicken und mehrfach zu verwenden. Python unterstützt außerdem Klassen, mit denen sich zusammengehörige Daten und Methoden organisieren lassen. Für diesen Ordnervergleich reichen normale Funktionen gut aus.

            Wir erklären den Code in der Reihenfolge, in der er gebraucht wird. Wir beginnen beim Startblock und gehen zu main(). Sobald dort eine Funktion aufgerufen wird, schauen wir uns deren Aufgabe an und kehren anschließend an die Aufrufstelle zurück.

            Hinweis zur Kursreihe

            Dieses Tutorial gehört zum Python-Grundkurs und setzt dieselbe Aufgabe wie die entsprechenden Batch- und PowerShell-7-Varianten um. Ihr könnt die verschiedenen Schreibweisen direkt vergleichen. Python verwendet hier nur seine Standardbibliothek; für die Zwischenablage wird das in Windows enthaltene clip.exe aufgerufen.

            Downloads zu diesem Teil

            Dateien für Python Grundkurs Teil 010:

            Download Python_Grundkurs_010_Fehlende_Dateien_vergleichen.zip

            Enthalten sind zwei Python-Skripte, je zwei Starter-Batchdateien und kurze Testhinweise. Die vollständigen Skripte findet ihr auch weiter unten zum Kopieren.

            Entpacken nach:

            C:\TOPTORIALS_CODE\020_Python_Grundkurs

            Testumgebung zum Mitmachen

            Testumgebung für Windows-Automatisierung:

            Download TOPTORIALS_Testdaten_Windows_Automatisierung_V001.zip

            Entpacken nach:

            C:\TOPTORIALS_CODE\1000_TESTBEREICH

            Verwendet die Vergleichsordner aus Teil 010. Kontrolliert nach dem Entpacken die tatsächlichen Verzeichnisnamen und passt die vorbereiteten Pfade im Python-Skript bei Bedarf an. Die Vergleichsordner werden vom Skript nicht selbst erstellt.

            Die feste Variante ist auf diese beiden Pfade vorbereitet:

            C:\TOPTORIALS_CODE\1000_TESTBEREICH\TOPTORIALS_Testdaten_Windows_Automatisierung_Python_V001\010_Fehlende_Dateien_vergleichen\01_Feste_Ordner_vergleichen\01_Ordner_1
            
            C:\TOPTORIALS_CODE\1000_TESTBEREICH\TOPTORIALS_Testdaten_Windows_Automatisierung_Python_V001\010_Fehlende_Dateien_vergleichen\01_Feste_Ordner_vergleichen\02_Ordner_2

            Alternativ könnt ihr zwei eigene Testordner anlegen oder die vorhandenen PowerShell-Testordner verwenden. Tragt dafür die entsprechenden Pfade in ORDNER1 und ORDNER2 ein.

            Sicherheitshinweis

            Beginnt mit Kopien unwichtiger Dateien und kontrolliert die angezeigten Ordnerpfade. Der Testmodus erstellt keine Ergebnisdateien. Bei SendTo wird jedoch auch im Testmodus der vorherige Inhalt der Zwischenablage durch die Berichte ersetzt.

            Ihr wisst ja, die Nutzung dieses Codes erfolgt natürlich wieder auf eigene Verantwortung. Ich übernehme keine Haftung für Datenverluste, unbeabsichtigte Änderungen oder andere Schäden, die durch die Verwendung des Skripts entstehen könnten.

            Voraussetzungen

            • Windows mit Python 3 und dem Python-Launcher py.
            • Leserechte für beide Vergleichsordner.
            • Im Echtmodus Schreibrechte im Skriptordner beziehungsweise in beiden SendTo-Ordnern.
            • Python-Datei und zugehörige Starterdateien liegen nebeneinander.
            • Es müssen keine zusätzlichen Python-Pakete installiert werden.

            Wenn auf eurem Rechner nur der Befehl python verfügbar ist, ersetzt in den Startern py -3 durch python. Die Option -X utf8 bleibt erhalten.

            Die beiden Varianten im Überblick

            Variante Vergleichsordner Ergebnis im Echtmodus
            Feste Ordner Direkt im Python-Skript eingetragen Ein gemeinsamer Bericht neben der Python-Datei
            SendTo Genau zwei übergebene Ordner Ein eigener Bericht in jedem Ordner; beide Berichte zusätzlich in der Zwischenablage
            C:\TOPTORIALS_CODE\020_Python_Grundkurs\010_Fehlende_Dateien_vergleichen\01_Feste_Ordner_vergleichen
            010_fehlende_dateien_vergleichen.py
            010_fehlende_dateien_vergleichen_starter_batch_test.bat
            010_fehlende_dateien_vergleichen_starter_batch.bat
            C:\TOPTORIALS_CODE\020_Python_Grundkurs\010_Fehlende_Dateien_vergleichen\02_SendTo_Zwei_Ordner_vergleichen
            010_sendto_zwei_ordner_vergleichen.py
            010_sendto_zwei_ordner_vergleichen_starter_batch_test.bat
            010_sendto_zwei_ordner_vergleichen_starter_batch.bat

            Die beiden Starter einer Variante haben denselben Inhalt. Der tatsächliche Dateiname entscheidet über den Modus. Ihr könnt den Teststarter kopieren und bei der Kopie _test aus dem Namen entfernen.

            Vergleich mit oder ohne Dateiendung

            Ordner 1 Ordner 2 JA: mit Endung NEIN: ohne Endung
            Bild_001.CR3 Bild_001.jpg Jeweils anderer Name Gemeinsamer Name Bild_001
            Bericht.docx Bericht.pdf Jeweils anderer Name Gemeinsamer Name Bericht
            Notiz.txt notiz.TXT Gleicher Vergleichsname Gleicher Vergleichsname
            Bild_002.jpg Kein entsprechender Name Bild_002.jpg fehlt in Ordner 2 Bild_002 fehlt in Ordner 2

            JA verwendet Path.name, also den vollständigen Dateinamen. NEIN verwendet Path.stem, also den Namen ohne letzte Dateiendung. Aus Bericht.final.pdf wird beispielsweise Bericht.final. Normale Dateien ohne Endung bleiben mit ihrem Namen im Vergleich.

            Vergleichsschlüssel werden mit casefold() vorbereitet. Dadurch wird Groß-/Kleinschreibung beim Vergleich ignoriert. Bei manchen Unicode-Sonderfällen arbeitet das anders als der PowerShell-Vergleich; für die hier verwendeten Kursbeispiele sind die Ergebnisse gleich.

            Testmodus und Echtmodus

            Verhalten Mit _test Ohne _test
            Vergleichen und Ergebnisse anzeigen Ja Ja
            Berichte speichern Nein Ja
            SendTo-Zwischenablage aktualisieren Ja Ja
            Projektdateien umbenennen, verschieben oder löschen Nein Nein

            Die Frage nach JA oder NEIN betrifft ausschließlich die Dateiendung. Sie ist keine zusätzliche Sicherheitsbestätigung. Ohne _test werden die Ergebnisdateien direkt nach dem Vergleich gespeichert.

            Direkt zu den Abschnitten

            • Normale Variante ausprobieren
            • Vollständiges Python-Skript
            • Python entlang des Programmablaufs erklärt
            • List Comprehensions ausführlich erklärt
            • Starter-Batchdatei erklärt
            • SendTo einrichten und ausprobieren
            • SendTo-Skript und zusätzliche Funktionen
            • Argumente und Parameter der Berichtsfunktion

            1. Die normale Variante ausprobieren

            1. Öffnet 010_fehlende_dateien_vergleichen.py und kontrolliert TESTBEREICH, ORDNER1 und ORDNER2.
            2. Startet die Batchdatei mit _test im Namen. Im Fenster erscheint Testmodus: JA.
            3. Gebt JA ein, um vollständige Dateinamen zu vergleichen.
            4. Startet erneut und gebt NEIN ein, um die letzte Dateiendung zu ignorieren.
            5. Startet anschließend die Batchdatei ohne _test. Zusätzlich zur Anzeige entsteht nun ein Bericht im Ordner der Python-Datei.
            vergleich_ergebnis_2026-09-16_14-30-00.txt

            Die normale Variante speichert beide Vergleichsrichtungen gemeinsam in dieser Datei. Der Ablageort hängt vom Python-Skript ab und nicht davon, aus welchem Arbeitsverzeichnis ihr es gestartet habt.

            Vollständiges Python-Skript: feste Ordner

            # ============================================================
            # TOPTORIALS OFFICE - Python Grundkurs Teil 010
            # Script: 010_fehlende_dateien_vergleichen.py
            # Beschreibung:
            # Vergleicht zwei fest eingetragene Ordner.
            # Vergleich anhand der Dateinamen, wahlweise ohne letzte Endung.
            # Groß-/Kleinschreibung wird ignoriert. Kein Inhaltsvergleich.
            # Nur direkt enthaltene Dateien, einschließlich versteckter Dateien.
            # Unterordner werden nicht durchsucht.
            #
            # Autor: Chris
            # YouTube: https://www.youtube.com/@TOPTORIALS-OFFICE
            # Webseite: https://www.toptorials.com
            # Version: Grundkurs 1.0
            # Stand: 2026-09-16
            #
            # Hinweise:
            # Mit _test im Starternamen wird --test übergeben:
            # Ergebnis anzeigen, aber keine Ergebnisdateien erstellen.
            # Ohne _test werden zusätzlich Berichte mit Zeitstempel gespeichert.
            # Bestehende gleichnamige Berichte werden nicht überschrieben.
            # Der Ergebnisbericht wird im Ordner dieses Skripts gespeichert.
            # Zuerst mit Testdaten arbeiten. Nutzung auf eigene Verantwortung.
            # ============================================================
            
            from datetime import datetime
            from pathlib import Path
            import sys
            
            # Diese beiden Ordner können an die eigene Umgebung angepasst werden.
            TESTBEREICH = Path(r"C:\TOPTORIALS_CODE\1000_TESTBEREICH\TOPTORIALS_Testdaten_Windows_Automatisierung_Python_V001")
            ORDNER1 = TESTBEREICH / "010_Fehlende_Dateien_vergleichen/01_Feste_Ordner_vergleichen/01_Ordner_1"
            ORDNER2 = TESTBEREICH / "010_Fehlende_Dateien_vergleichen/01_Feste_Ordner_vergleichen/02_Ordner_2"
            
            def dateien_einlesen(ordner, berichte_ausschliessen=False):
                dateien = []
                for datei in ordner.iterdir():
                    if not datei.is_file():
                        continue
                    name = datei.name.casefold()
                    if berichte_ausschliessen and name.startswith("vergleich_fehlt_hier_") and name.endswith(".txt"):
                        continue
                    dateien.append(datei)
                return sorted(dateien, key=lambda datei: datei.name.casefold())
            
            
            def namen_sammeln(dateien, mit_endung):
                # Der Vergleichsschlüssel ignoriert Groß- und Kleinschreibung.
                # Als Wert bleibt die ursprüngliche Schreibweise erhalten.
                namen = {}
                for datei in dateien:
                    name = datei.name if mit_endung else datei.stem
                    namen.setdefault(name.casefold(), name)
                return namen
            
            
            def bericht_speichern(pfad, zeilen):
                # "x" erstellt eine neue Datei und verhindert das Überschreiben.
                with pfad.open("x", encoding="utf-8") as datei:
                    datei.write("\n".join(zeilen) + "\n")
            
            def main():
                try:
                    argumente = sys.argv[1:]
                    if argumente not in ([], ["--test"]):
                        raise ValueError("Erlaubt ist nur der optionale Schalter --test.")
                    test = "--test" in argumente
                    ordner1, ordner2 = ORDNER1, ORDNER2
                    for ordner in (ordner1, ordner2):
                        if not ordner.is_dir():
                            raise ValueError(f"Ordner nicht gefunden: {ordner}")
            
                    print(f"\nTestmodus: {'JA' if test else 'NEIN'}\n")
                    print(f"Ordner 1: {ordner1}")
                    print(f"Ordner 2: {ordner2}\n")
                    print("JA   = vollständigen Dateinamen vergleichen")
                    print("NEIN = Dateiendung ignorieren\n")
                    eingabe = input("Dateiendung berücksichtigen? JA/NEIN: ").strip().upper()
                    if eingabe not in ("JA", "NEIN"):
                        raise ValueError("Bitte JA oder NEIN eingeben.")
            
                    mit_endung = eingabe == "JA"
                    dateien1 = dateien_einlesen(ordner1)
                    dateien2 = dateien_einlesen(ordner2)
                    namen1 = namen_sammeln(dateien1, mit_endung)
                    namen2 = namen_sammeln(dateien2, mit_endung)
                    fehlt1 = [name for schluessel, name in namen2.items() if schluessel not in namen1]
                    fehlt2 = [name for schluessel, name in namen1.items() if schluessel not in namen2]
            
                    bericht = [
                        "Vergleichsergebnis", "",
                        f"Ordner 1: {ordner1}", f"Ordner 2: {ordner2}",
                        f"Dateiendung berücksichtigen: {eingabe}", "",
                        "Dateien aus Ordner 2, die in Ordner 1 fehlen:",
                        *fehlt1, "",
                        "Dateien aus Ordner 1, die in Ordner 2 fehlen:",
                        *fehlt2, "", "Zusammenfassung:",
                        f"Dateien in Ordner 1: {len(dateien1)}",
                        f"Dateien in Ordner 2: {len(dateien2)}",
                        f"Fehlende Namen in Ordner 1: {len(fehlt1)}",
                        f"Fehlende Namen in Ordner 2: {len(fehlt2)}",
                    ]
                    print("\n" + "\n".join(bericht) + "\n")
                    if test:
                        print("Testmodus: Es wurde keine Ergebnisdatei erstellt.")
                    else:
                        zeitstempel = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
                        ausgabe = Path(__file__).resolve().parent / f"vergleich_ergebnis_{zeitstempel}.txt"
                        bericht_speichern(ausgabe, bericht)
                        print(f"Ergebnisdatei erstellt: {ausgabe}")
            
                    return 0
                except (OSError, ValueError, EOFError) as fehler:
                    print(f"\nFehler: {fehler}")
                    return 1
            
            
            if __name__ == "__main__":
                sys.exit(main())

            2. Den Python-Code entlang seines Ablaufs verstehen

            Der Startblock am Ende der Datei

            if __name__ == "__main__":
                sys.exit(main())

            Python verarbeitet die Datei zunächst von oben nach unten: Es lädt die importierten Module, setzt die vorbereiteten Ordnerpfade und führt die Funktionsdefinitionen aus. Dabei werden die Funktionen angelegt; ihre Funktionskörper laufen noch nicht. Unser eigentlicher Vergleich startet erst mit dem Aufruf von main().

            Wird die Datei direkt gestartet, erhält die besondere Variable __name__ den Wert "__main__". Die Bedingung ist dann erfüllt. Wird die Datei stattdessen als Modul importiert, enthält __name__ den Modulnamen und dieser Startblock wird übersprungen. Die definierten Funktionen können so von einem anderen Skript verwendet werden, ohne automatisch den Vergleich zu starten.

            main ist kein vorgeschriebener Funktionsname, sondern eine verbreitete Konvention für die Hauptfunktion. Zuerst läuft main() vollständig. Ihr Rückgabewert wird danach an sys.exit() übergeben. Bei uns bedeutet 0 Erfolg und 1 einen behandelten Fehler. Die Starter-Batchdatei kann diesen Status übernehmen.

            Module und vorbereitete Ordnerpfade

            datetime liefert Datum und Uhrzeit, Path verarbeitet Dateisystempfade und sys stellt unter anderem die Programmargumente und exit() bereit. Die großgeschriebenen Namen für die vorbereiteten Pfade sind eine Konvention für feste Einstellungen; Python verbietet ihre spätere Änderung dadurch nicht.

            ORDNER1 = Path(r"C:\Test\Ordner_1")
            ORDNER2 = Path(r"C:\Test\Ordner_2")

            So könnt ihr alternativ vollständige eigene Pfade eintragen. Das vorangestellte r verhindert bei diesem String, dass Python Backslashes bereits als Teil eigener Escape-Sequenzen verarbeitet. Path erzeugt daraus ein Pfadobjekt. Mit / können wir bei einem solchen Objekt weitere Pfadbestandteile anhängen; hier ist das keine Division.

            In main(): Argumente und Ordner prüfen

            argumente = sys.argv[1:]
            if argumente not in ([], ["--test"]):
                raise ValueError("Erlaubt ist nur der optionale Schalter --test.")
            test = "--test" in argumente

            sys.argv enthält den Skriptaufruf und die übergebenen Argumente. Mit [1:] übernehmen wir die Einträge ab Position 1; der Eintrag an Position 0 bezeichnet das gestartete Skript. Die normale Variante akzeptiert eine leere Argumentliste oder genau ["--test"]. Andere Angaben lösen mit raise einen Fehler aus.

            ordner1, ordner2 = ORDNER1, ORDNER2
            for ordner in (ordner1, ordner2):
                if not ordner.is_dir():
                    raise ValueError(f"Ordner nicht gefunden: {ordner}")

            Die beiden vorbereiteten Pfade werden den lokalen Variablen zugewiesen. Die Schleife geht das Tupel (ordner1, ordner2) nacheinander durch. In ordner steht jeweils der aktuell geprüfte Pfad. is_dir() prüft, ob es sich um einen vorhandenen Ordner handelt.

            Eingabe und f-Strings

            print(f"\nTestmodus: {'JA' if test else 'NEIN'}\n")

            Das f vor dem String erlaubt Ausdrücke in geschweiften Klammern. Der bedingte Ausdruck liefert JA, wenn test wahr ist, andernfalls NEIN.
            steht in diesem normalen String für einen Zeilenumbruch.

            eingabe = input("Dateiendung berücksichtigen? JA/NEIN: ").strip().upper()
            mit_endung = eingabe == "JA"

            input() nimmt die Eingabe entgegen. strip() entfernt Leerraum am Anfang und Ende, upper() wandelt den Text in Großbuchstaben um. Damit werden auch ja und nein akzeptiert. Die Prüfung dazwischen erlaubt nur JA oder NEIN. Der Vergleich eingabe == "JA" ergibt den Wahrheitswert True oder False, der in mit_endung gespeichert wird.

            Beim ersten Funktionsaufruf: dateien_einlesen()

            dateien1 = dateien_einlesen(ordner1)
            dateien2 = dateien_einlesen(ordner2)

            Wir übergeben einen Ordner an die Funktion. Dort durchläuft ordner.iterdir() die direkt enthaltenen Elemente. is_file() begrenzt die Auswahl auf Dateien. continue überspringt den restlichen aktuellen Schleifendurchlauf. Mit append() werden passende Pfadobjekte zur Liste hinzugefügt.

            return sorted(dateien, key=lambda datei: datei.name.casefold())

            sorted() liefert eine sortierte Liste. Über key geben wir an, welcher Wert für die Sortierung verwendet wird. lambda definiert dafür eine kleine namenlose Funktion: Sie erhält ein Dateiobjekt und liefert dessen mit casefold() vorbereiteten Namen. Sortiert werden die Pfadobjekte nach diesen Namen; die Dateinamen selbst werden nicht verändert. return gibt die fertige Liste an die Aufrufstelle zurück.

            Warum steht in der Definition berichte_ausschliessen=False?

            def dateien_einlesen(ordner, berichte_ausschliessen=False):

            Die Funktion besitzt zwei Parameter. ordner hat keinen Standardwert und muss deshalb angegeben werden. Für berichte_ausschliessen ist False als Standardwert festgelegt. Wird kein zweites Argument übergeben, verwendet die Funktion automatisch diesen Wert. Der Ausschluss von Berichtsnamen ist dann deaktiviert.

            dateien_einlesen(ordner1)
            dateien_einlesen(ordner1, False)
            dateien_einlesen(ordner1, berichte_ausschliessen=False)

            Diese drei Aufrufe wählen dieselbe Einstellung. Ein ausdrücklich übergebener Wert ersetzt den Standardwert für den jeweiligen Aufruf. Bei SendTo verwenden wir später deshalb:

            dateien_einlesen(ordner1, berichte_ausschliessen=True)

            Hier wird der zweite Parameter benannt, damit seine Bedeutung schon beim Lesen des Aufrufs deutlich ist. Ohne =False wäre dieser Parameter in unserer Definition ebenfalls verpflichtend:

            def dateien_einlesen(ordner, berichte_ausschliessen):
                ...
            
            # Bei dieser Definition fehlt ein erforderliches Argument:
            dateien_einlesen(ordner1)  # TypeError

            Merksatz:

            =False legt den Standardwert fest. Wird das zweite Argument weggelassen, verwendet Python automatisch False. Ein ausdrücklich übergebener Wert ersetzt den Standardwert für diesen Aufruf.

            Vergleichsnamen mit namen_sammeln() vorbereiten

            namen1 = namen_sammeln(dateien1, mit_endung)
            namen2 = namen_sammeln(dateien2, mit_endung)

            Diese Funktion erhält die Dateiliste und die Einstellung zur Endung. Sie erstellt mit {} ein leeres Dictionary. Ein Dictionary ordnet einem Schlüssel einen Wert zu. Wir verwenden den vorbereiteten Namen als Schlüssel und die ursprüngliche Schreibweise als Wert.

            name = datei.name if mit_endung else datei.stem
            namen.setdefault(name.casefold(), name)

            Der bedingte Ausdruck wählt den vollständigen Namen oder den Basisnamen aus. setdefault() fügt den Schlüssel mit dem angegebenen Wert nur hinzu, wenn dieser Schlüssel noch nicht vorhanden ist. Ein bereits vorhandener Eintrag bleibt erhalten. So bewahren wir für die Anzeige die Schreibweise des ersten erfassten Namens.

            Liegen Bild.jpg und Bild.png im selben Ordner, ergeben sie ohne Endung beide den Vergleichsschlüssel bild. Das sind zwei Dateien, aber nur ein Vergleichsname. Deshalb unterscheiden wir im Bericht Dateianzahlen und fehlende Namen.

            List Comprehensions: Welche Namen fehlen?

            fehlt1 = [name for schluessel, name in namen2.items() if schluessel not in namen1]
            fehlt2 = [name for schluessel, name in namen1.items() if schluessel not in namen2]

            Die eckigen Klammern erzeugen jeweils eine neue Liste. Diese kompakte Schreibweise heißt List Comprehension. Zum Verstehen beginnen wir beim for und schauen uns die erste Zeile auf mehrere Zeilen verteilt an:

            fehlt1 = [
                name
                for schluessel, name in namen2.items()
                if schluessel not in namen1
            ]
            Bestandteil Bedeutung
            namen2.items() Liefert die Schlüssel-Wert-Paare aus dem zweiten Dictionary.
            for schluessel, name in ... Geht die Paare durch und verteilt jedes Paar auf die zwei Variablen.
            if schluessel not in namen1 Übernimmt nur Einträge, deren Schlüssel im ersten Dictionary fehlt.
            name am Anfang Bestimmt den Wert, der in die neue Liste aufgenommen wird.
            fehlt1 = ... Speichert die fertige Liste der Namen, die im ersten Ordner fehlen.

            Bei einem Dictionary prüfen in und not in die Schlüssel. Die Bedingung sucht also nicht nach einem Teil eines Dateinamens und auch nicht in den gespeicherten Werten. Sie prüft, ob genau dieser Vergleichsschlüssel vorhanden ist. Für die Ausgabe übernehmen wir anschließend den zugehörigen ursprünglichen Namen.

            namen1 = {"bild_001": "Bild_001", "bild_002": "Bild_002"}
            namen2 = {"bild_001": "Bild_001", "bild_003": "Bild_003"}

            Der Schlüssel bild_001 ist in beiden Dictionaries vorhanden und wird nicht in die Fehlstellenliste aufgenommen. bild_003 fehlt dagegen in namen1. Deshalb entsteht:

            fehlt1 = ["Bild_003"]

            Dieselbe Aufgabe lässt sich mit einer gewöhnlichen Schleife schreiben:

            fehlt1 = []
            
            for schluessel, name in namen2.items():
                if schluessel not in namen1:
                    fehlt1.append(name)

            Wir legen eine leere Liste an, prüfen die Einträge und hängen einen Namen nur dann an, wenn sein Schlüssel im ersten Dictionary fehlt. Die List Comprehension fasst genau diesen Ablauf kürzer zusammen.

            Für fehlt2 tauschen wir die Dictionaries aus: Nun prüfen wir Namen aus Ordner 1 gegen Ordner 2. Im Beispiel ergibt sich fehlt2 = ["Bild_002"]. Die Zahl im Variablennamen bezeichnet also immer den Ordner, in dem etwas fehlt.

            Den Bericht zusammenstellen und anzeigen

            bericht = [
                "Dateien aus Ordner 2, die in Ordner 1 fehlen:",
                *fehlt1,
                "",
                f"Fehlende Namen in Ordner 1: {len(fehlt1)}",
            ]

            Die Berichtszeilen liegen ebenfalls in einer Liste. *fehlt1 packt die Namen einzeln in diese äußere Liste aus. Ohne Sternchen würde die gesamte Liste als ein einzelnes verschachteltes Element eingefügt. Der leere String "" erzeugt später eine Leerzeile. len() liefert die Anzahl der Elemente.

            print("\n".join(bericht))

            join() verbindet die Textzeilen zu einem zusammenhängenden String. Zwischen je zwei Einträgen wird hier ein Zeilenumbruch eingefügt. print() zeigt diesen Text an.

            Im Echtmodus: Zeitstempel, Zielpfad und Speichern

            zeitstempel = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
            ausgabe = Path(__file__).resolve().parent / f"vergleich_ergebnis_{zeitstempel}.txt"
            bericht_speichern(ausgabe, bericht)

            datetime.now() liefert die aktuelle lokale Zeit. strftime() formatiert sie als Jahr, Monat, Tag, Stunde, Minute und Sekunde. __file__ bezeichnet diese Python-Datei. resolve() ermittelt den aufgelösten absoluten Pfad und parent dessen übergeordneten Ordner. Mit / hängen wir den Berichtsnamen an.

            def bericht_speichern(pfad, zeilen):
                with pfad.open("x", encoding="utf-8") as datei:
                    datei.write("\n".join(zeilen) + "\n")

            Die Funktion erhält den Zielpfad und die Berichtszeilen. Der Modus "x" erstellt eine neue Datei und löst einen Fehler aus, wenn sie schon existiert. encoding="utf-8" legt die Textkodierung fest. with sorgt dafür, dass die geöffnete Datei beim Verlassen des Blocks geschlossen wird, auch bei einem Fehler. write() schreibt den verbundenen Text.

            Der Zeitstempel hat eine Genauigkeit von einer Sekunde. Zwei Durchläufe innerhalb derselben Sekunde können deshalb denselben Berichtsnamen ergeben. In diesem Fall schützt "x" den bereits vorhandenen Bericht vor dem Überschreiben.

            Fehler behandeln und zum Startblock zurückkehren

            Der try-Block enthält den normalen Ablauf. except (OSError, ValueError, EOFError) as fehler fängt die angegebenen Fehlerarten ab: beispielsweise Dateizugriffsfehler, ungültige Eingaben oder eine beendete Eingabe. Der Fehlertext wird angezeigt und main() gibt 1 zurück. Bei erfolgreicher Verarbeitung gibt die Funktion 0 zurück. Anschließend erhält sys.exit() diesen Wert.

            3. Starter-Batchdatei der normalen Variante

            @echo off
            setlocal DisableDelayedExpansion
            REM ============================================================
            REM TOPTORIALS OFFICE - Python Grundkurs Teil 010
            REM Beschreibung: Startet den Vergleich zweier Ordner.
            REM Autor: Chris
            REM YouTube: https://www.youtube.com/@TOPTORIALS-OFFICE
            REM Webseite: https://www.toptorials.com
            REM Version: Grundkurs 1.0 - Stand: 2026-09-16
            REM
            REM Mit _test im Namen: keine Ergebnisdateien erstellen.
            REM Ohne _test im Namen: Ergebnisberichte speichern.
            REM Python 3 und Python Launcher py werden benoetigt.
            REM Die Python-Datei muss neben dieser Batchdatei liegen.
            REM Die Vergleichsordner werden in der Python-Datei eingetragen.
            REM Der Name der echten Batchdatei steuert den Testmodus.
            REM Nutzung auf eigene Verantwortung. Zuerst mit Testdaten pruefen.
            REM ============================================================
            
            chcp 65001 >nul
            set "STARTERNAME=%~n0"
            set "TESTPARAMETER="
            if /i not "%STARTERNAME:_test=%"=="%STARTERNAME%" set "TESTPARAMETER=--test"
            
            py -3 -X utf8 "%~dp0010_fehlende_dateien_vergleichen.py" %TESTPARAMETER%
            set "EXITCODE=%ERRORLEVEL%"
            echo.
            pause
            exit /b %EXITCODE%

            @echo off unterdrückt die zusätzliche Anzeige der Befehle. setlocal DisableDelayedExpansion begrenzt Variableneinstellungen auf den Starter und deaktiviert die verzögerte Variablenersetzung. Dadurch werden Ausrufezeichen in übergebenen Pfaden nicht als solche Variablenmarkierungen verarbeitet. chcp 65001 stellt die Konsolencodepage auf UTF-8.

            Den Testmodus ohne find erkennen

            set "STARTERNAME=%~n0"
            set "TESTPARAMETER="
            if /i not "%STARTERNAME:_test=%"=="%STARTERNAME%" set "TESTPARAMETER=--test"

            %~n0 liefert den Namen dieser Batchdatei ohne Erweiterung. TESTPARAMETER beginnt leer. Für den Vergleich wird links _test probeweise durch einen leeren Text ersetzt. Rechts steht der unveränderte Name. Sind die beiden Texte ungleich, war _test enthalten und der Testparameter wird gesetzt. /i macht den Vergleich unabhängig von Groß-/Kleinschreibung.

            Ursprünglicher Name: 010_vergleichen_starter_batch_test
            Vergleich links:    010_vergleichen_starter_batch
            Vergleich rechts:   010_vergleichen_starter_batch_test

            Merksatz:

            Wir entfernen _test probeweise aus dem Starternamen. Unterscheidet sich das Ergebnis vom ursprünglichen Namen, war _test enthalten und der Testmodus wird aktiviert.

            Dabei wird weder die Batchdatei umbenannt noch der Inhalt von STARTERNAME dauerhaft verändert. Die Ersetzung liefert nur den Text für diesen Vergleich.

            Die bisherige Lösung mit find konnte dieselbe Aufgabe erfüllen. Hier brauchen wir dafür keine Pipe und kein zusätzlich gestartetes find.exe. Die direkte Ersetzung ist kompakter; ein spürbarer Geschwindigkeitsvorteil ist bei diesen kleinen Startern nicht entscheidend.

            Python aufrufen und den Rückgabecode übernehmen

            py -3 -X utf8 "%~dp0010_fehlende_dateien_vergleichen.py" %TESTPARAMETER%

            py -3 startet Python 3 über den Windows-Launcher. -X utf8 aktiviert den UTF-8-Modus. %~dp0 liefert den Ordner der Batchdatei einschließlich des abschließenden Backslashes. Direkt danach folgt der Python-Dateiname. Die Anführungszeichen halten einen Pfad mit Leerzeichen zusammen. Am Ende wird je nach Modus --test oder kein zusätzlicher Text eingesetzt.

            %ERRORLEVEL% wird unmittelbar nach dem Python-Aufruf in EXITCODE gespeichert. echo. erzeugt eine Leerzeile und pause hält das Fenster offen. exit /b %EXITCODE% beendet danach den Starter mit dem zuvor gespeicherten Status.

            4. SendTo einrichten und ausprobieren

            1. Lasst Python-Datei und Starter im Ordner 02_SendTo_Zwei_Ordner_vergleichen.
            2. Erstellt Verknüpfungen zu den beiden Starter-Batchdateien.
            3. Öffnet shell:sendto in der Adresszeile des Explorers und legt die Verknüpfungen dort ab.
            4. Markiert genau zwei Vergleichsordner und wählt Rechtsklick – Senden an – den Teststarter.
            5. Vergleicht zuerst mit JA, anschließend mit NEIN. Fügt das Ergebnis mit Strg+V in einen Texteditor ein.
            6. Startet ohne _test und kontrolliert den Bericht in jedem ausgewählten Ordner.

            Verknüpfungen zu den Startern verwenden.

            Kopiert nicht nur die Batchdateien in den SendTo-Ordner: Der Starter erwartet die Python-Datei neben sich. Der Name der echten Starterdatei steuert den Modus, nicht der Anzeigename ihrer Verknüpfung.

            Als Vergleichsziele erwartet diese Version zwei Dateisystemordner. Windows-Verknüpfungen zu Ordnern, also .lnk-Dateien, werden nicht aufgelöst. Für die gemeinsame Auswahl im Explorer legt ihr die beiden Testordner am besten in dasselbe übergeordnete Verzeichnis.

            Ordner_A/vergleich_fehlt_hier_2026-09-16_14-30-00.txt
            Ordner_B/vergleich_fehlt_hier_2026-09-16_14-30-00.txt

            Jeder Bericht zeigt die Namen, die in seinem eigenen Ordner fehlen. Vorhandene Dateien nach dem Muster vergleich_fehlt_hier_*.txt werden beim SendTo-Vergleich ausgeschlossen. Das verhindert, dass frühere Berichte spätere Vergleiche beeinflussen. Der Filter erkennt jedoch nur den Namen: Auch eine selbst erstellte Datei mit einem solchen Namen wird ausgeschlossen. Die normale Variante aktiviert diesen Filter nicht.

            Vollständiges Python-Skript: SendTo

            # ============================================================
            # TOPTORIALS OFFICE - Python Grundkurs Teil 010
            # Script: 010_sendto_zwei_ordner_vergleichen.py
            # Beschreibung:
            # Vergleicht genau zwei übergebene Ordner.
            # Vergleich anhand der Dateinamen, wahlweise ohne letzte Endung.
            # Groß-/Kleinschreibung wird ignoriert. Kein Inhaltsvergleich.
            # Nur direkt enthaltene Dateien, einschließlich versteckter Dateien.
            # Unterordner werden nicht durchsucht.
            #
            # Autor: Chris
            # YouTube: https://www.youtube.com/@TOPTORIALS-OFFICE
            # Webseite: https://www.toptorials.com
            # Version: Grundkurs 1.0
            # Stand: 2026-09-16
            #
            # Hinweise:
            # Mit _test im Starternamen wird --test übergeben:
            # Ergebnis anzeigen, aber keine Ergebnisdateien erstellen.
            # Ohne _test werden zusätzlich Berichte mit Zeitstempel gespeichert.
            # Bestehende gleichnamige Berichte werden nicht überschrieben.
            # SendTo: Bericht je Ordner; Zwischenablage auch im Testmodus.
            # Zuerst mit Testdaten arbeiten. Nutzung auf eigene Verantwortung.
            # ============================================================
            
            from datetime import datetime
            from pathlib import Path
            import sys
            import subprocess
            
            def dateien_einlesen(ordner, berichte_ausschliessen=False):
                dateien = []
                for datei in ordner.iterdir():
                    if not datei.is_file():
                        continue
                    name = datei.name.casefold()
                    if berichte_ausschliessen and name.startswith("vergleich_fehlt_hier_") and name.endswith(".txt"):
                        continue
                    dateien.append(datei)
                return sorted(dateien, key=lambda datei: datei.name.casefold())
            
            
            def namen_sammeln(dateien, mit_endung):
                # Der Vergleichsschlüssel ignoriert Groß- und Kleinschreibung.
                # Als Wert bleibt die ursprüngliche Schreibweise erhalten.
                namen = {}
                for datei in dateien:
                    name = datei.name if mit_endung else datei.stem
                    namen.setdefault(name.casefold(), name)
                return namen
            
            
            def bericht_speichern(pfad, zeilen):
                # "x" erstellt eine neue Datei und verhindert das Überschreiben.
                with pfad.open("x", encoding="utf-8") as datei:
                    datei.write("\n".join(zeilen) + "\n")
            
            def bericht_erstellen(dieser_ordner, anderer_ordner, eingabe, anzahl, andere_anzahl, fehlt):
                return [
                    "Vergleichsergebnis", "",
                    f"Dieser Ordner: {dieser_ordner}",
                    f"Vergleich mit: {anderer_ordner}",
                    f"Dateiendung berücksichtigen: {eingabe}", "",
                    "Dateien, die in diesem Ordner fehlen:",
                    *fehlt, "", "Zusammenfassung:",
                    f"Dateien in diesem Ordner: {anzahl}",
                    f"Dateien im Vergleichsordner: {andere_anzahl}",
                    f"Fehlende Namen in diesem Ordner: {len(fehlt)}",
                ]
            
            
            def zwischenablage_kopieren(text):
                # clip.exe erwartet Unicode-Text hier als UTF-16LE.
                subprocess.run(["clip.exe"], input=text.encode("utf-16le"), check=True)
            
            
            def main():
                try:
                    argumente = sys.argv[1:]
                    test = "--test" in argumente
                    elemente = [wert for wert in argumente if wert != "--test"]
                    if len(elemente) != 2:
                        raise ValueError("Bitte genau zwei Ordner über Senden an übergeben.")
                    ordner1, ordner2 = [Path(wert).resolve() for wert in elemente]
                    for ordner in (ordner1, ordner2):
                        if not ordner.is_dir():
                            raise ValueError(f"Kein Dateisystemordner: {ordner}")
                    if ordner1.samefile(ordner2):
                        raise ValueError("Bitte zwei unterschiedliche Ordner auswählen.")
            
                    print(f"\nTestmodus: {'JA' if test else 'NEIN'}\n")
                    print(f"Ordner 1: {ordner1}")
                    print(f"Ordner 2: {ordner2}\n")
                    print("JA   = vollständigen Dateinamen vergleichen")
                    print("NEIN = Dateiendung ignorieren\n")
                    eingabe = input("Dateiendung berücksichtigen? JA/NEIN: ").strip().upper()
                    if eingabe not in ("JA", "NEIN"):
                        raise ValueError("Bitte JA oder NEIN eingeben.")
            
                    mit_endung = eingabe == "JA"
                    dateien1 = dateien_einlesen(ordner1, berichte_ausschliessen=True)
                    dateien2 = dateien_einlesen(ordner2, berichte_ausschliessen=True)
                    namen1 = namen_sammeln(dateien1, mit_endung)
                    namen2 = namen_sammeln(dateien2, mit_endung)
                    fehlt1 = [name for schluessel, name in namen2.items() if schluessel not in namen1]
                    fehlt2 = [name for schluessel, name in namen1.items() if schluessel not in namen2]
            
                    bericht1 = bericht_erstellen(ordner1, ordner2, eingabe, len(dateien1), len(dateien2), fehlt1)
                    bericht2 = bericht_erstellen(ordner2, ordner1, eingabe, len(dateien2), len(dateien1), fehlt2)
                    gesamt = "\n".join(bericht1 + ["", "-" * 60, ""] + bericht2)
                    print("\n" + gesamt + "\n")
            
                    # Die Zwischenablage wird in beiden Modi aktualisiert.
                    try:
                        zwischenablage_kopieren(gesamt.replace("\n", "\r\n"))
                        print("Die Berichte wurden in die Zwischenablage kopiert.")
                    except (OSError, subprocess.SubprocessError) as fehler:
                        print(f"Hinweis: Zwischenablage konnte nicht aktualisiert werden: {fehler}")
            
                    if test:
                        print("Testmodus: Es wurden keine Ergebnisdateien erstellt.")
                    else:
                        zeitstempel = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
                        dateiname = f"vergleich_fehlt_hier_{zeitstempel}.txt"
                        for ordner, bericht in ((ordner1, bericht1), (ordner2, bericht2)):
                            ausgabe = ordner / dateiname
                            bericht_speichern(ausgabe, bericht)
                            print(f"Ergebnisdatei erstellt: {ausgabe}")
            
                    return 0
                except (OSError, ValueError, EOFError) as fehler:
                    print(f"\nFehler: {fehler}")
                    return 1
            
            
            if __name__ == "__main__":
                sys.exit(main())

            5. Die zusätzlichen SendTo-Funktionen verstehen

            Argumente sammeln und zwei Ordner prüfen

            elemente = [wert for wert in argumente if wert != "--test"]
            ordner1, ordner2 = [Path(wert).resolve() for wert in elemente]

            Die erste List Comprehension übernimmt alle Argumente außer --test. Anschließend prüft das Skript, ob genau zwei Elemente vorhanden sind. Erst dann wandelt die zweite List Comprehension beide Texte in aufgelöste Pfadobjekte um. Die beiden Ergebnisse werden durch Entpacken auf ordner1 und ordner2 verteilt.

            Wie zuvor prüft is_dir(), ob beide Pfade Ordner sind. Mit samefile() prüfen wir außerdem, ob beide Pfade auf denselben Dateisystemeintrag zeigen. In diesem Fall wird der Vergleich mit einer verständlichen Meldung abgebrochen.

            Die Dateiliste ohne alte Berichte einlesen

            dateien1 = dateien_einlesen(ordner1, berichte_ausschliessen=True)

            Jetzt nutzen wir bewusst das zweite Argument unserer bereits bekannten Funktion. Weil es True ist, wird die Prüfung mit startswith() und endswith() wirksam. Ein Name muss mit vergleich_fehlt_hier_ beginnen und mit .txt enden, damit die Datei übersprungen wird. Namen sammeln und fehlende Namen ermitteln funktioniert danach wie in der normalen Variante.

            Argumente und Parameter von bericht_erstellen()

            def bericht_erstellen(dieser_ordner, anderer_ordner, eingabe, anzahl, andere_anzahl, fehlt):
            bericht1 = bericht_erstellen(
                ordner1,
                ordner2,
                eingabe,
                len(dateien1),
                len(dateien2),
                fehlt1
            )

            Die Definition benennt die Parameter, mit denen die Funktion intern arbeitet. Beim Aufruf übergeben wir konkrete Argumente. Hier werden sie anhand ihrer Position zugeordnet: erstes Argument zum ersten Parameter, zweites zum zweiten und so weiter. Die Namen der Variablen beim Aufruf müssen dafür nicht mit den Parameternamen übereinstimmen.

            Argument beim ersten Aufruf Parameter in der Funktion Bedeutung
            ordner1 dieser_ordner Der Ordner, dessen fehlende Namen wir beschreiben
            ordner2 anderer_ordner Der Vergleichsordner
            eingabe eingabe JA oder NEIN zur Dateiendung
            len(dateien1) anzahl Dateianzahl dieses Ordners
            len(dateien2) andere_anzahl Dateianzahl des Vergleichsordners
            fehlt1 fehlt Liste der Namen, die hier fehlen

            len(dateien1) und len(dateien2) werden berechnet, bevor die Berichtsfunktion ausgeführt wird. Die Funktion bekommt hier also die ermittelten Zahlen. fehlt1 ist dagegen die Liste der fehlenden Namen. Mit return [...] gibt die Funktion eine Liste fertiger Berichtszeilen zurück. Diese Rückgabe landet in bericht1.

            bericht2 = bericht_erstellen(
                ordner2,
                ordner1,
                eingabe,
                len(dateien2),
                len(dateien1),
                fehlt2
            )

            Beim zweiten Aufruf wechseln wir die Perspektive. Nun ist Ordner 2 dieser_ordner. Deshalb tauschen wir auch die beiden Dateianzahlen und übergeben fehlt2. Die Einstellung zur Dateiendung bleibt gleich. Beide Berichte verwenden dadurch dieselbe Vorlage, die nur an einer Stelle gepflegt werden muss.

            Als Lernvergleich lässt sich der erste Aufruf auch mit benannten Argumenten schreiben:

            bericht1 = bericht_erstellen(
                dieser_ordner=ordner1,
                anderer_ordner=ordner2,
                eingabe=eingabe,
                anzahl=len(dateien1),
                andere_anzahl=len(dateien2),
                fehlt=fehlt1
            )

            Damit wird die Zuordnung direkt sichtbar. In den vollständigen Skripten oben bleibt die kompakte Positionsschreibweise erhalten. Durch die geöffneten runden Klammern darf Python den Aufruf über mehrere Zeilen fortsetzen; zusätzliche Zeichen zur Zeilenfortsetzung werden hier nicht gebraucht.

            Berichte verbinden und in die Zwischenablage kopieren

            gesamt = "\n".join(bericht1 + ["", "-" * 60, ""] + bericht2)

            Das Pluszeichen verbindet die drei Listen zu einer Liste. "-" * 60 erzeugt eine Trennlinie aus 60 Bindestrichen. join() verbindet die Zeilen anschließend zu einem Text für Anzeige und Zwischenablage.

            zwischenablage_kopieren(gesamt.replace("\n", "\r\n"))
            
            def zwischenablage_kopieren(text):
                subprocess.run(["clip.exe"], input=text.encode("utf-16le"), check=True)

            Vor dem Aufruf ersetzen wir die verwendeten Zeilenumbrüche durch Windows-Zeilenumbrüche. Die Funktion startet mit subprocess.run() das Windows-Programm clip.exe. encode("utf-16le") wandelt den Text in die dafür übergebenen Bytes um. Über input gelangen sie an die Standardeingabe des Programms. check=True lässt einen Fehler auslösen, wenn das Programm einen von null verschiedenen Rückgabecode liefert.

            Ein eigener try/except-Bereich behandelt Fehler der Zwischenablage. Dann erscheint ein Hinweis, aber der Vergleich und das mögliche Speichern können weiterlaufen. Der Aufruf steht vor der Unterscheidung zwischen Test- und Echtmodus. Deshalb wird die Zwischenablage in beiden Modi aktualisiert.

            Für jeden Ordner den passenden Bericht speichern

            for ordner, bericht in ((ordner1, bericht1), (ordner2, bericht2)):
                ausgabe = ordner / dateiname
                bericht_speichern(ausgabe, bericht)

            Hier durchlaufen wir zwei Paare. Im ersten Durchlauf stehen ordner1 und bericht1 in den Schleifenvariablen. Im zweiten Durchlauf sind es ordner2 und bericht2. Das gemeinsame dateiname wird an den jeweiligen Ordner angehängt. Unsere bereits erklärte Speicherfunktion schreibt dann den passenden Bericht.

            Die Dateien werden nacheinander geschrieben. Falls der zweite Schreibvorgang fehlschlägt, bleibt der erste erfolgreich erstellte Bericht bestehen. Eine bereits vorhandene gleichnamige Datei wird durch den Modus "x" geschützt.

            6. Starter-Batchdatei für SendTo

            @echo off
            setlocal DisableDelayedExpansion
            REM ============================================================
            REM TOPTORIALS OFFICE - Python Grundkurs Teil 010
            REM Beschreibung: Startet den Vergleich zweier Ordner.
            REM Autor: Chris
            REM YouTube: https://www.youtube.com/@TOPTORIALS-OFFICE
            REM Webseite: https://www.toptorials.com
            REM Version: Grundkurs 1.0 - Stand: 2026-09-16
            REM
            REM Mit _test im Namen: keine Ergebnisdateien erstellen.
            REM Ohne _test im Namen: Ergebnisberichte speichern.
            REM Python 3 und Python Launcher py werden benoetigt.
            REM Die Python-Datei muss neben dieser Batchdatei liegen.
            REM SendTo: Verknuepfung hierher anlegen; genau zwei Ordner senden.
            REM Zwischenablage wird auch im Testmodus aktualisiert.
            REM Der Name der echten Batchdatei steuert den Testmodus.
            REM Nutzung auf eigene Verantwortung. Zuerst mit Testdaten pruefen.
            REM ============================================================
            
            chcp 65001 >nul
            set "STARTERNAME=%~n0"
            set "TESTPARAMETER="
            if /i not "%STARTERNAME:_test=%"=="%STARTERNAME%" set "TESTPARAMETER=--test"
            
            py -3 -X utf8 "%~dp0010_sendto_zwei_ordner_vergleichen.py" %TESTPARAMETER% %*
            set "EXITCODE=%ERRORLEVEL%"
            echo.
            pause
            exit /b %EXITCODE%

            Der Aufbau entspricht dem normalen Starter. Zusätzlich steht am Ende des Python-Aufrufs %*. Damit reicht die Batchdatei alle übergebenen Argumente weiter. Bei der gewünschten Explorer-Auswahl sind das die beiden Ordnerpfade. Das Python-Skript prüft anschließend selbst, ob genau zwei gültige, unterschiedliche Ordner übergeben wurden.

            Häufige Fragen und mögliche Fehler

            Beobachtung Erklärung oder Lösung
            py wird nicht gefunden Python-Launcher prüfen oder py -3 im Starter durch python ersetzen.
            Ordner nicht gefunden Die festen Pfade kontrollieren; die Testordner müssen bereits existieren.
            Python-Datei wird über SendTo nicht gefunden Verknüpfung zum echten Starter verwenden; Python-Datei muss neben dem Starter liegen.
            Weniger fehlende Namen als Dateien Ohne Endung können mehrere Dateien denselben Vergleichsnamen ergeben.
            Ein alter SendTo-Bericht fehlt in der Dateiliste Dateien mit dem reservierten Muster vergleich_fehlt_hier_*.txt werden ausgeschlossen.
            Kein Bericht im Testmodus Das ist vorgesehen. Ohne _test im tatsächlichen Starternamen werden Berichte gespeichert.
            Zwischenablage enthält neuen Text trotz Testmodus SendTo aktualisiert sie in beiden Modi.
            FileExistsError beim Speichern Ein gleichnamiger Bericht existiert bereits; er wird nicht überschrieben.
            Nur ein SendTo-Bericht wurde erstellt Das Speichern erfolgt nacheinander; die Fehlermeldung zum zweiten Ziel prüfen.

            Zusammenfassung

            • Zwei Ordner werden anhand ihrer Dateinamen in beide Richtungen verglichen.
            • JA berücksichtigt die Endung, NEIN verwendet den Basisnamen.
            • Funktionen teilen den Ablauf in verständliche Aufgaben auf.
            • Der Startblock ruft main() auf und gibt den Rückgabecode weiter.
            • Ein Standardwert macht ein Argument beim Aufruf optional.
            • Dictionaries speichern Vergleichsschlüssel und ursprüngliche Namen.
            • List Comprehensions erzeugen die beiden Listen fehlender Namen.
            • Die Berichtsfunktion wird bei SendTo mit vertauschten Argumenten wiederverwendet.
            • Im Testmodus werden keine Berichte gespeichert; SendTo aktualisiert trotzdem die Zwischenablage.
            • Im Echtmodus landet der normale Bericht im Skriptordner, die SendTo-Berichte in den ausgewählten Ordnern.
            • Bestehende gleichnamige Berichte werden nicht überschrieben.

            Damit habt ihr zwei praktische Varianten zum Ordnervergleich und zugleich einen Einblick in den Aufbau von Python-Skripten mit mehreren Funktionen. Probiert die verschiedenen Vergleichseinstellungen mit den Testdaten aus und verfolgt dabei, welche Werte zwischen den Funktionen übergeben werden.

            Video zu diesem Tutorial:

             

            Das könnte Dich auch interessieren

            Keine Einträge gefunden

            Schreibe einen Kommentar Antwort abbrechen

            Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

            INTERESSANTE SEITEN

            • TUTORIALS SCHNELLER FINDEN
            • SCHNELLER RECHNEN LERNEN
            • MATHE AUFGABEN GENERATOR
            • LINIEN UND KARO GENERATOR
            • VORLAGEN ZUM AUSDRUCKEN
            • BINGO-SCHEIN-GENERATOR
            • MEINE WUNSCHLISTE
            • Symbole zum Kopieren

            Content

            • Microsoft Excel Tutorials
            • Microsoft Excel VBA Tutorials
            • Microsoft Word Tutorials
            • Microsoft Powerpoint Tutorials
            • Microsoft Windows 10 Tutorials
            • Google Tabellen Tutorials
            • Google Tabellen Script Tutorials
            • Google Docs Tutorials
            • LibreOffice Calc Tutorials
            • Libre Office Writer Tutorials
            • LibreOffice Impress Tutorials
            • OpenOffice Calc Tutorials
            • OpenOffice Writer Tutorials
            • OpenOffice Impress Tutorials
            • WPS Spreadsheets Tutorials
            • WPS Spreadsheets Tutorials

            Neue Beiträge

            • Python Grundkurs Teil 010: Zwei Ordner vergleichen und fehlende Dateien finden
            • PowerShell 7 Grundkurs Teil 010: Zwei Ordner vergleichen und fehlende Dateien finden
            • Batch Grundkurs 010: Fehlende Dateien in zwei Ordnern finden
            • Python Grundkurs Teil 009: Projektordner mit Datum und Protokolldatei sichern
            • PowerShell 7 Grundkurs Teil 009: Projektordner mit Datum und Logdatei sichern

            Neue Kommentare

            • Chris zu Zeilen, Spalten, Fenster fixieren (FreeOffice PlanMaker)
            • Herbert Krüger zu Zeilen, Spalten, Fenster fixieren (FreeOffice PlanMaker)
            • Chris zu Tutorial Wunsch Liste
            • Rupert zu Tutorial Wunsch Liste
            • Axel zu Datumsformat anpassen (LibreOffice Calc)
            • Klaus zu Dynamischen Monatskalender erstellen + Download (LibreOffice Calc)

            Schlagwörter-Wolke

            anfänger Anleitung anpassen ausrechnen auswahlliste Bedingte Formatierung berechnen Calc Datum Download Dropdownliste einfügen erstellen Excel FreeOffice Funktion google hinzufügen Jahresplan Kalender Lernvideo LibreOffice löschen Makro markieren Microsoft OpenOffice PlanMaker programmierung script SendTo spreadsheets Sverweis Tabelle tabellen Tutorial VBA Video Wenn Wenn Funktion Windows Automatisierung wps spreadsheets Zeilen Zelle Zellen
            KONTAKT   IMPRESSUM    DATENSCHUTZERKLÄRUNG    HAFTUNGSAUSSCHLUSS (Disclaimer)   © copyright TOPTORIALS