PowerShell 7 Grundkurs Teil 010: Zwei Ordner vergleichen und fehlende Dateien finden
Worum geht es in diesem Teil?
In diesem Teil vergleichen wir die Dateinamen aus zwei Ordnern. Ihr seht anschließend, welche Namen nur in einem der beiden Ordner vorkommen. Wahlweise berücksichtigen wir die Dateiendung oder vergleichen ausschließlich den Basisnamen. Das ist beispielsweise hilfreich, wenn ihr PDF-Dateien mit den dazugehörigen Word-Dokumenten abgleichen möchtet.
Wir verwenden zwei Varianten: einen Vergleich mit fest eingetragenen Ordnern und einen Vergleich über das Windows-Menü Senden an. Im Echtmodus werden die Ergebnisse zusätzlich als Textdateien gespeichert.
Was ist das Ziel?
Der Vergleich erfolgt in beide Richtungen. Fehlt ein Name in Ordner 1, erscheint er in dessen Fehlstellenliste. Entsprechend erhalten wir eine zweite Liste für Ordner 2. Die vorhandenen Projektdateien werden dabei weder umbenannt noch kopiert oder gelöscht.
Ein Namensvergleich ist kein Inhaltsvergleich.
Gleiche Dateinamen bedeuten nicht, dass die Dateien denselben Inhalt besitzen. Dateigrößen, Änderungszeiten und Prüfsummen werden nicht geprüft. Auch fehlende Unterordner werden nicht ermittelt.
Warum ist dieser Teil wichtig?
Wir verbinden Dateilisten, Arrays und Filter zu einem übersichtlichen Vergleich. Besonders interessant sind die Auswahl zwischen Name und BaseName, das Zusammenfassen gleicher Namen mit Sort-Object -Unique und die Prüfung mit -notcontains. Funktionen vermeiden in der SendTo-Version wiederholten Code.
Hinweis zur Kursreihe
Dieses Tutorial gehört zum PowerShell-7-Grundkurs und orientiert sich an der entsprechenden Batchaufgabe. So könnt ihr die unterschiedlichen Schreibweisen miteinander vergleichen. Die hier gezeigte Fassung verwendet die kompakte normale Variante und die korrigierte SendTo-Version.
Downloads zu diesem Teil
Dateien für PowerShell 7 Grundkurs Teil 010
Download Skriptpaket: 010_Fehlende_Dateien_vergleichen
Die vollständigen Skripte stehen zusätzlich weiter unten zum Kopieren bereit.
Vorgesehener Hauptordner:
C:\TOPTORIALS_CODE\010_PowerShell_7_Grundkurs\010_Fehlende_Dateien_vergleichen
Testumgebung zum Mitmachen
Testumgebung für Windows-Automatisierung:Download TOPTORIALS_Testdaten_Windows_Automatisierung_V001.zip
Entpacken nach:
C:\TOPTORIALS_CODE\1000_TESTBEREICH
Für diesen Teil verwendet ihr die beiden Vergleichsordner aus der PowerShell-7-Testumgebung. Prüft nach dem Entpacken die unten angegebenen Pfade und passt sie bei Bedarf im Skript an.
Die feste Variante erwartet die beiden folgenden Testordner. Wenn eure Testumgebung an einem anderen Ort liegt, passt $testbereich, $ordner1 und $ordner2 entsprechend an. Die Skripte erstellen diese Vergleichsordner nicht selbst.
C:\TOPTORIALS_CODE\1000_TESTBEREICH\TOPTORIALS_Testdaten_Windows_Automatisierung_PowerShell_7_V001\
010_Fehlende_Dateien_vergleichen\01_Feste_Ordner_vergleichen\01_Ordner_1
C:\TOPTORIALS_CODE\1000_TESTBEREICH\TOPTORIALS_Testdaten_Windows_Automatisierung_PowerShell_7_V001\
010_Fehlende_Dateien_vergleichen\01_Feste_Ordner_vergleichen\02_Ordner_2
Für eigene Tests genügen zwei Ordner mit einigen gemeinsamen und einigen unterschiedlichen Dateinamen. Fügt außerdem Dateien mit gleichem Basisnamen und unterschiedlicher Endung hinzu, um beide Vergleichsarten auszuprobieren.
Sicherheitshinweis
Beginnt mit unwichtigen Testdaten. Im Testmodus entstehen keine Ergebnisdateien. Bei SendTo wird allerdings auch im Testmodus die Zwischenablage mit dem Vergleichsergebnis 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 PowerShell 7, erreichbar über
pwsh.exe. - Leserechte für beide Vergleichsordner.
- Im Echtmodus Schreibrechte im Skriptordner beziehungsweise in beiden SendTo-Vergleichsordnern.
- PowerShell-Datei und passender Starter liegen gemeinsam im jeweiligen Kursordner.
Enthaltene Ordner und Dateien
C:\TOPTORIALS_CODE\010_PowerShell_7_Grundkurs\010_Fehlende_Dateien_vergleichen\01_Feste_Ordner_vergleichen
010_fehlende_dateien_vergleichen.ps1
010_fehlende_dateien_vergleichen_starter_batch_test.bat
010_fehlende_dateien_vergleichen_starter_batch.bat
C:\TOPTORIALS_CODE\010_PowerShell_7_Grundkurs\010_Fehlende_Dateien_vergleichen\02_SendTo_Zwei_Ordner_vergleichen
010_sendto_zwei_ordner_vergleichen.ps1
010_sendto_zwei_ordner_vergleichen_starter_batch_test.bat
010_sendto_zwei_ordner_vergleichen_starter_batch.bat
Die beiden Starter einer Variante besitzen denselben Inhalt. Nur der Name entscheidet über den Modus. Zum Erstellen des Echtmodus-Starters könnt ihr den Teststarter kopieren und _test aus dessen Namen entfernen. Alle hier verwendeten Skriptdateinamen sind kleingeschrieben.
Vergleich mit oder ohne Dateiendung
| Ordner 1 | Ordner 2 | Mit Endung: JA | Ohne Endung: NEIN |
|---|---|---|---|
| Bericht.docx | Bericht.pdf | Beide Namen fehlen jeweils im anderen Ordner | Bericht ist in beiden Ordnern vorhanden |
| Foto.jpg | foto.JPG | Gleicher Name beim Vergleich | Gleicher Basisname |
| Notiz.txt | kein entsprechender Name | Notiz.txt fehlt in Ordner 2 | Notiz fehlt in Ordner 2 |
Die Eingaben JA, ja, NEIN und nein werden akzeptiert. Trim() entfernt Leerraum am Anfang und Ende der Eingabe. Eine andere Eingabe beendet den Durchlauf mit einer Fehlermeldung.
Auch Namen wie Bericht.final.pdf sind möglich: Ohne Endung vergleichen wir Bericht.final. Es wird die letzte Dateiendung entfernt. Dateien ohne Endung werden ebenfalls berücksichtigt.
Dateianzahl und fehlende Namen
Die Anzahl der Dateien und die Anzahl fehlender Namen sind unterschiedliche Werte. Liegen Bild.jpg und Bild.png in Ordner 1, sind das zwei Dateien. Ohne Endung entsteht daraus durch Sort-Object -Unique nur der Vergleichsname Bild. Fehlt dieser in Ordner 2, wird ein fehlender Name gemeldet.
Testmodus und Echtmodus
| Verhalten | Testmodus | Echtmodus |
|---|---|---|
| Vergleich und Bildschirmausgabe | Ja | Ja |
| Ergebnisdateien speichern | Nein | Ja |
| Zwischenablage bei SendTo aktualisieren | Ja | Ja |
| Projektdateien verändern | Nein | Nein |
Der Testmodus wird aktiviert, wenn _test im tatsächlichen Namen der Starter-Batchdatei vorkommt. Die Anzeige lautet dann Testmodus: JA. Der Name einer SendTo-Verknüpfung allein ändert den Modus nicht.
Die Abfrage zur Dateiendung ist keine zusätzliche Sicherheitsbestätigung. Ohne _test werden die Berichte nach dem Vergleich direkt gespeichert.
Wo werden die Ergebnisdateien gespeichert?
| Variante | Ablageort | Berichtsname |
|---|---|---|
| Feste Ordner | Neben der PowerShell-Datei | vergleich_ergebnis_ZEITSTEMPEL.txt |
| SendTo | Jeweils in beiden ausgewählten Ordnern | vergleich_fehlt_hier_ZEITSTEMPEL.txt |
Bei SendTo nennt jeder Bericht die Namen, die in seinem eigenen Ordner fehlen. Die Zwischenablage enthält beide Berichte. In der normalen Variante werden beide Richtungen gemeinsam in einer Datei gespeichert.
C:\Test\Ordner_A\vergleich_fehlt_hier_2026-09-15_12-30-00.txt
C:\Test\Ordner_B\vergleich_fehlt_hier_2026-09-15_12-30-00.txt
Variante 1: Zwei feste Ordner vergleichen
- Speichert Skript und Starter in
01_Feste_Ordner_vergleichen. - Prüft die beiden fest eingetragenen Vergleichspfade.
- Startet zunächst die Batchdatei mit
_testim Namen. - Wählt, ob die Dateiendung berücksichtigt werden soll.
- Kontrolliert die Fehlstellenlisten und Zähler.
- Verwendet den Starter ohne
_test, wenn ihr den Bericht speichern möchtet.
Vollständiges PowerShell-7-Skript
<#
============================================================
TOPTORIALS OFFICE - PowerShell 7 Grundkurs Teil 10
Script: 010_fehlende_dateien_vergleichen.ps1
Beschreibung:
Vergleicht zwei feste Ordner anhand ihrer Dateinamen.
Optional wird die Dateiendung beim Vergleich ignoriert.
Unterordner werden nicht durchsucht.
Im Testmodus wird das Ergebnis nur angezeigt.
Im Echtmodus entsteht eine Textdatei im Scriptordner.
Autor: Chris
YouTube: https://www.youtube.com/@TOPTORIALS-OFFICE
Webseite: https://www.toptorials.com
Version: 1.0
Hinweis:
Die Starter-Batchdatei aktiviert mit -Test den Testmodus,
solange _test in ihrem Dateinamen steht.
============================================================
#>
param (
[switch]$Test
)
$ErrorActionPreference = 'Stop'
$testbereich = 'C:\TOPTORIALS_CODE\1000_TESTBEREICH\TOPTORIALS_Testdaten_Windows_Automatisierung_PowerShell_7_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"
$zeitstempel = Get-Date -Format 'yyyy-MM-dd_HH-mm-ss'
$ausgabe = Join-Path $PSScriptRoot "vergleich_ergebnis_$zeitstempel.txt"
Write-Host
Write-Host "Testmodus: $(if ($Test) { 'JA' } else { 'NEIN' })"
Write-Host
Write-Host "Ordner 1: $ordner1"
Write-Host "Ordner 2: $ordner2"
Write-Host
Write-Host 'JA = vollständigen Dateinamen vergleichen'
Write-Host 'NEIN = Dateiendung ignorieren'
Write-Host
try {
foreach ($ordner in @($ordner1, $ordner2)) {
if (-not (Test-Path -LiteralPath $ordner -PathType Container)) {
throw "Ordner nicht gefunden: $ordner"
}
}
$eingabe = (Read-Host 'Dateiendung berücksichtigen? JA/NEIN').Trim()
if ($eingabe -notin @('JA', 'NEIN')) {
throw 'Bitte JA oder NEIN eingeben.'
}
$eigenschaft = if ($eingabe -eq 'JA') { 'Name' } else { 'BaseName' }
$dateien1 = @(Get-ChildItem -LiteralPath $ordner1 -File -Force)
$dateien2 = @(Get-ChildItem -LiteralPath $ordner2 -File -Force)
$namen1 = @($dateien1.$eigenschaft | Sort-Object -Unique)
$namen2 = @($dateien2.$eigenschaft | Sort-Object -Unique)
$fehlt1 = @($namen2 | Where-Object { $namen1 -notcontains $_ })
$fehlt2 = @($namen1 | Where-Object { $namen2 -notcontains $_ })
$bericht = @(
'Vergleichsergebnis'
''
"Ordner 1: $ordner1"
"Ordner 2: $ordner2"
"Dateiendung berücksichtigen: $($eingabe.ToUpper())"
''
'Dateien aus Ordner 2, die in Ordner 1 fehlen:'
$fehlt1
''
'Dateien aus Ordner 1, die in Ordner 2 fehlen:'
$fehlt2
''
'Zusammenfassung:'
"Dateien in Ordner 1: $($dateien1.Count)"
"Dateien in Ordner 2: $($dateien2.Count)"
"Fehlende Namen in Ordner 1: $($fehlt1.Count)"
"Fehlende Namen in Ordner 2: $($fehlt2.Count)"
)
Write-Host
$bericht | ForEach-Object { Write-Host $_ }
Write-Host
if ($Test) {
Write-Host 'Testmodus: Es wurde keine Ergebnisdatei erstellt.'
}
else {
$bericht | Out-File -LiteralPath $ausgabe -Encoding utf8 -NoClobber
Write-Host "Ergebnisdatei erstellt: $ausgabe"
}
}
catch {
Write-Host
Write-Host "Fehler: $($_.Exception.Message)" -ForegroundColor Red
exit 1
}
Starter-Batchdatei für feste Ordner
@echo off
REM ============================================================
REM TOPTORIALS OFFICE - PowerShell 7 Grundkurs Teil 10
REM Startet den Vergleich zweier fest eingetragener Ordner.
REM Mit _test im Namen: keine Ergebnisdateien erstellen.
REM Ohne _test im Namen: Ergebnisdatei(en) erstellen.
REM Die PowerShell-Datei muss neben dieser Batchdatei liegen.
REM ============================================================
setlocal DisableDelayedExpansion
set "STARTERNAME=%~n0"
set "TESTPARAMETER="
if /i not "%STARTERNAME:_test=%"=="%STARTERNAME%" set "TESTPARAMETER=-Test"
pwsh.exe -NoLogo -NoProfile -ExecutionPolicy Bypass -File "%~dp0010_fehlende_dateien_vergleichen.ps1" %TESTPARAMETER%
set "EXITCODE=%ERRORLEVEL%"
echo.
pause
exit /b %EXITCODE%
So funktioniert der Vergleich
$eigenschaft = if ($eingabe -eq 'JA') { 'Name' } else { 'BaseName' }
Die Variable enthält den Namen der gewünschten Objekteigenschaft. Name liefert den vollständigen Dateinamen; BaseName liefert den Namen ohne letzte Endung. Dadurch benötigen wir keine zwei getrennten Vergleichsabläufe.
$namen1 = @($dateien1.$eigenschaft | Sort-Object -Unique)
PowerShell liest die ausgewählte Eigenschaft der Dateien aus. Sort-Object -Unique sortiert die Namen und fasst gleiche Namen zusammen. @(...) sorgt dafür, dass eine Sammlung entsteht, auch wenn kein oder nur ein Name vorhanden ist.
$fehlt1 = @($namen2 | Where-Object { $namen1 -notcontains $_ })
Hier prüfen wir jeden Namen aus Ordner 2. $_ steht für den gerade geprüften Namen. Enthält die Namensliste von Ordner 1 diesen Namen nicht, bleibt er im Ergebnis. Deshalb heißt das Ergebnis $fehlt1. Die zweite Abfrage arbeitet entsprechend in der Gegenrichtung. Die verwendeten Stringvergleiche ignorieren Groß- und Kleinschreibung.
Variante 2: Zwei Ordner über Senden an vergleichen
SendTo-Verknüpfungen einrichten
- Speichert das SendTo-Skript und die passenden Starter in
02_SendTo_Zwei_Ordner_vergleichen. - Öffnet mit Windows + R den Ausführen-Dialog.
- Gebt
shell:sendtoein. - Legt dort Verknüpfungen zu den Starter-Batchdateien an. Die Originaldateien bleiben im Kursordner.
- Benennt die Verknüpfungen bei Bedarf verständlich, beispielsweise „PowerShell 10 – Ordnervergleich Test“ und „PowerShell 10 – Ordnervergleich“.
So wird die SendTo-Variante angewendet
Markiert im Explorer genau zwei Ordner und wählt über das Kontextmenü Senden an die passende Verknüpfung. Je nach Windows-Kontextmenü findet ihr den Eintrag unter Weitere Optionen anzeigen. Prüft die angezeigten Pfade und beantwortet die Frage zur Dateiendung. Welche Auswahl als Ordner 1 erscheint, ist für das Ergebnis unerheblich: Der Vergleich erfolgt in beide Richtungen.
Vollständiges PowerShell-7-Skript
<#
============================================================
TOPTORIALS OFFICE - PowerShell 7 Grundkurs Teil 10
Script: 010_sendto_zwei_ordner_vergleichen.ps1
Beschreibung:
Vergleicht genau zwei übergebene Ordner anhand der Dateinamen.
Optional wird die Dateiendung beim Vergleich ignoriert.
Unterordner werden nicht durchsucht.
Im Testmodus wird das Ergebnis nur angezeigt und zusätzlich
in die Zwischenablage kopiert.
Im Echtmodus wird außerdem in jedem Vergleichsordner eine
Textdatei mit den dort fehlenden Namen erstellt.
Autor: Chris
YouTube: https://www.youtube.com/@TOPTORIALS-OFFICE
Webseite: https://www.toptorials.com
Version: 1.1
Hinweis:
Die Starter-Batchdatei aktiviert mit -Test den Testmodus,
solange _test in ihrem Dateinamen steht.
Dateien mit dem Muster vergleich_fehlt_hier_*.txt sind
für Ergebnisberichte reserviert und vom Vergleich ausgeschlossen.
============================================================
#>
param (
[switch]$Test,
[Parameter(Position = 0, ValueFromRemainingArguments = $true)]
[string[]]$Elemente
)
$ErrorActionPreference = 'Stop'
function Get-Vergleichsdateien {
param ([string]$Ordner)
Get-ChildItem -LiteralPath $Ordner -File -Force |
Where-Object { $_.Name -notlike 'vergleich_fehlt_hier_*.txt' }
}
function Get-Bericht {
param (
[string]$DieserOrdner,
[string]$AndererOrdner,
[string]$MitEndung,
[int]$AnzahlHier,
[int]$AnzahlDort,
[string[]]$FehlendeNamen
)
@(
'Vergleichsergebnis'
''
"Dieser Ordner: $DieserOrdner"
"Vergleich mit: $AndererOrdner"
"Dateiendung berücksichtigen: $MitEndung"
''
'Dateien, die in diesem Ordner fehlen:'
$FehlendeNamen
''
'Zusammenfassung:'
"Dateien in diesem Ordner: $AnzahlHier"
"Dateien im Vergleichsordner: $AnzahlDort"
"Fehlende Namen in diesem Ordner: $($FehlendeNamen.Count)"
)
}
Write-Host
Write-Host "Testmodus: $(if ($Test) { 'JA' } else { 'NEIN' })"
Write-Host
try {
if ($Elemente.Count -ne 2) {
throw 'Bitte genau zwei Ordner über Senden an übergeben.'
}
$ordner = @(
foreach ($element in $Elemente) {
$eintrag = Get-Item -LiteralPath $element -Force
if ($eintrag -isnot [System.IO.DirectoryInfo]) {
throw "Kein Dateisystemordner: $element"
}
[System.IO.Path]::TrimEndingDirectorySeparator($eintrag.FullName)
}
)
if ($ordner[0] -eq $ordner[1]) {
throw 'Bitte zwei unterschiedliche Ordner auswählen.'
}
Write-Host "Ordner 1: $($ordner[0])"
Write-Host "Ordner 2: $($ordner[1])"
Write-Host
Write-Host 'JA = vollständigen Dateinamen vergleichen'
Write-Host 'NEIN = Dateiendung ignorieren'
Write-Host
$eingabe = (Read-Host 'Dateiendung berücksichtigen? JA/NEIN').Trim()
if ($eingabe -notin @('JA', 'NEIN')) {
throw 'Bitte JA oder NEIN eingeben.'
}
$mitEndung = $eingabe.ToUpper()
$eigenschaft = if ($eingabe -eq 'JA') { 'Name' } else { 'BaseName' }
$dateien1 = @(Get-Vergleichsdateien -Ordner $ordner[0])
$dateien2 = @(Get-Vergleichsdateien -Ordner $ordner[1])
$namen1 = @($dateien1.$eigenschaft | Sort-Object -Unique)
$namen2 = @($dateien2.$eigenschaft | Sort-Object -Unique)
$fehlt1 = @($namen2 | Where-Object { $namen1 -notcontains $_ })
$fehlt2 = @($namen1 | Where-Object { $namen2 -notcontains $_ })
$bericht1 = @(Get-Bericht `
-DieserOrdner $ordner[0] -AndererOrdner $ordner[1] `
-MitEndung $mitEndung `
-AnzahlHier $dateien1.Count -AnzahlDort $dateien2.Count `
-FehlendeNamen $fehlt1)
$bericht2 = @(Get-Bericht `
-DieserOrdner $ordner[1] -AndererOrdner $ordner[0] `
-MitEndung $mitEndung `
-AnzahlHier $dateien2.Count -AnzahlDort $dateien1.Count `
-FehlendeNamen $fehlt2)
$gesamtbericht = $bericht1 + @('', '--------------------', '') + $bericht2
Write-Host
$gesamtbericht | ForEach-Object { Write-Host $_ }
Write-Host
try {
Set-Clipboard -Value ($gesamtbericht -join [Environment]::NewLine)
Write-Host 'Beide Berichte wurden in die Zwischenablage kopiert.'
}
catch {
Write-Host "Zwischenablage nicht verfügbar: $($_.Exception.Message)" `
-ForegroundColor Yellow
}
if ($Test) {
Write-Host 'Testmodus: Es wurden keine Ergebnisdateien erstellt.'
}
else {
$zeitstempel = Get-Date -Format 'yyyy-MM-dd_HH-mm-ss'
$dateiname = "vergleich_fehlt_hier_$zeitstempel.txt"
$ausgabe1 = Join-Path -Path $ordner[0] -ChildPath $dateiname
$ausgabe2 = Join-Path -Path $ordner[1] -ChildPath $dateiname
$bericht1 | Out-File -LiteralPath $ausgabe1 -Encoding utf8 -NoClobber
Write-Host "Ergebnisdatei erstellt: $ausgabe1"
$bericht2 | Out-File -LiteralPath $ausgabe2 -Encoding utf8 -NoClobber
Write-Host "Ergebnisdatei erstellt: $ausgabe2"
}
}
catch {
Write-Host
Write-Host "Fehler: $($_.Exception.Message)" -ForegroundColor Red
exit 1
}
Starter-Batchdatei für SendTo
@echo off
REM ============================================================
REM TOPTORIALS OFFICE - PowerShell 7 Grundkurs Teil 10
REM Uebergibt zwei markierte Ordner an das PowerShell-Script.
REM Mit _test im Namen: keine Ergebnisdateien erstellen.
REM Ohne _test im Namen: Ergebnisdatei(en) erstellen.
REM Die PowerShell-Datei muss neben dieser Batchdatei liegen.
REM ============================================================
setlocal DisableDelayedExpansion
set "STARTERNAME=%~n0"
set "TESTPARAMETER="
if /i not "%STARTERNAME:_test=%"=="%STARTERNAME%" set "TESTPARAMETER=-Test"
pwsh.exe -NoLogo -NoProfile -ExecutionPolicy Bypass -File "%~dp0010_sendto_zwei_ordner_vergleichen.ps1" %TESTPARAMETER% %*
set "EXITCODE=%ERRORLEVEL%"
echo.
pause
exit /b %EXITCODE%
So funktioniert die SendTo-Variante
[Parameter(Position = 0, ValueFromRemainingArguments = $true)]
[string[]]$Elemente
Der Parameter nimmt die übergebenen Pfade als Zeichenketten auf. Das Skript verlangt genau zwei Einträge. Get-Item -LiteralPath liest die jeweiligen Objekte. Die Prüfung auf DirectoryInfo stellt sicher, dass es sich um Dateisystemordner handelt.
[System.IO.Path]::TrimEndingDirectorySeparator($eintrag.FullName)
Diese Methode entfernt einen abschließenden Pfadtrenner, wenn er nicht zum Wurzelpfad gehört. Dadurch werden beispielsweise derselbe Ordner mit und ohne abschließenden Backslash einheitlich dargestellt. Das ist keine vollständige Erkennung aller möglichen Verweise auf denselben Speicherort, etwa über verschiedene Verknüpfungen oder Laufwerkszuordnungen.
Get-Vergleichsdateien liest die Dateien ein und schließt die reservierten Ergebnisnamen aus. Get-Bericht erstellt die Textzeilen für einen Ordner. Beim zweiten Aufruf tauschen wir die beiden Ordner und ihre Zähler aus. Dadurch zeigt jeder Bericht die richtige Vergleichsrichtung.
$ausgabe1 = Join-Path -Path $ordner[0] -ChildPath $dateiname
$ausgabe2 = Join-Path -Path $ordner[1] -ChildPath $dateiname
Die Berichte werden ausdrücklich in den übergebenen Ordnern gespeichert. $PSScriptRoot wird hierfür in der SendTo-Version nicht verwendet.
Welche Dateien werden berücksichtigt?
Get-ChildItem -File -Force liest direkt enthaltene Dateien einschließlich versteckter Dateien. Zugriffsrechte werden dadurch nicht umgangen. Weil -Recurse fehlt, werden Unterordner nicht durchsucht. Es gibt keinen allgemeinen Ausschluss von Endungen wie .ps1, .bat oder .log.
Nur die SendTo-Version schließt vergleich_fehlt_hier_*.txt aus. Damit erscheinen frühere Berichte weder in den Vergleichslisten noch in den Dateizählern. Das Muster ist reserviert: Auch eine selbst angelegte Datei mit einem passenden Namen wird ausgeschlossen.
Die normale Variante besitzt diesen Filter nicht. Wenn ihr den Skriptordner selbst als Vergleichsordner eintragt, können dort vorhandene Ergebnisdateien bei einem späteren Durchlauf mitgezählt werden. Verwendet für die feste Variante deshalb die vorgesehenen separaten Vergleichsordner.
Berichte, Zwischenablage und Fehlerbehandlung
$bericht | Out-File -LiteralPath $ausgabe -Encoding utf8 -NoClobber
Out-File speichert die Berichtszeilen als UTF-8-Text. -LiteralPath behandelt den Zielpfad wörtlich. -NoClobber verhindert das Überschreiben einer vorhandenen Datei mit demselben Namen. Der Zeitstempel hat eine Auflösung von einer Sekunde; bei einem Namenskonflikt meldet das Skript einen Fehler und vergibt keine automatische Zusatznummer.
Set-Clipboard -Value ($gesamtbericht -join [Environment]::NewLine)
-join verbindet die Zeilen zu einem Text. [Environment]::NewLine liefert unter Windows den passenden Zeilenumbruch. Set-Clipboard kopiert diesen Text in die Zwischenablage. Mit Strg + V könnt ihr ihn beispielsweise in einen Editor einfügen. Schlägt der Zugriff auf die Zwischenablage fehl, erscheint eine gelbe Meldung; der übrige Ablauf wird fortgesetzt.
$ErrorActionPreference = 'Stop' sorgt dafür, dass entsprechende PowerShell-Fehler im catch-Block behandelt werden. throw löst unsere eigenen verständlichen Fehlermeldungen aus. Bei einem Abbruch liefert exit 1 einen Fehlercode an die Starter-Batchdatei.
Die beiden SendTo-Berichte werden nacheinander gespeichert. Wenn das Schreiben im zweiten Ordner fehlschlägt, kann der erste Bericht bereits vorhanden sein. Die Ausgabe meldet jeden erfolgreich gespeicherten Bericht einzeln.
So funktionieren die Starter-Batchdateien
| Eintrag | Bedeutung |
|---|---|
| setlocal DisableDelayedExpansion | Deaktiviert verzögerte Variablenersetzung; Ausrufezeichen in übergebenen Pfaden bleiben erhalten. |
| %~n0 | Name des tatsächlichen Starters ohne Endung. |
| %STARTERNAME:_test=% | Entfernt _test aus dem Namen für die anschließende Prüfung. |
| -Test | Aktiviert den PowerShell-Schalter für den Testmodus. |
| %~dp0 | Laufwerk und Ordner der Starter-Batchdatei. |
| %* | Reicht bei SendTo alle übergebenen Argumente weiter. |
| -NoProfile | Startet ohne persönliche PowerShell-Profildateien. |
| -ExecutionPolicy Bypass | Setzt die Ausführungsrichtlinie für den gestarteten Prozess; es ist keine dauerhafte Systemänderung. |
| %ERRORLEVEL% | Übernimmt den Rückgabecode des PowerShell-Aufrufs. |
| pause | Hält das Fenster für die Kontrolle der Ausgabe offen. |
Typische Fehler und mögliche Ursachen
SendTo schreibt einen Bericht im Skriptordner
Prüft den tatsächlichen Inhalt von 010_sendto_zwei_ordner_vergleichen.ps1. Stehen dort feste Pfade und Join-Path $PSScriptRoot für die Ausgabe, wurde vermutlich die normale Version hineinkopiert. Der SendTo-Code benötigt $Elemente und zwei Ausgabeziele in den übergebenen Ordnern.
Das PowerShell-Skript wird nicht gefunden
Dateiname im Starter und tatsächlicher PS1-Dateiname müssen zusammenpassen. Die PS1-Datei liegt neben dem Originalstarter. Im SendTo-Ordner verwendet ihr Verknüpfungen zu diesem Starter, keine losgelösten Kopien der Batchdatei.
Es werden keine Berichte erstellt
Kontrolliert die Modusanzeige. Bei Testmodus: JA ist das beabsichtigt. Im Echtmodus können fehlende Schreibrechte oder eine schon vorhandene gleichnamige Ergebnisdatei das Speichern verhindern. Beachtet die angezeigte Fehlermeldung.
Ordner nicht gefunden oder falsche Anzahl
Prüft bei der normalen Variante die festen Pfade. SendTo erwartet genau zwei Ordner; einzelne Dateien, eine leere Auswahl oder mehr als zwei Einträge sind nicht zulässig.
Keine fehlenden Namen, obwohl die Dateien unterschiedlich sind
Der Vergleich untersucht ausschließlich die Namen. Unterschiedliche Inhalte bei gleichem Namen bleiben unentdeckt. Bei ignorierter Endung gelten beispielsweise Bericht.pdf und Bericht.docx als derselbe Vergleichsname.
PowerShell 7 wurde nicht gefunden
Der Starter benötigt pwsh.exe. Prüft in einem neuen Konsolenfenster mit pwsh --version, ob PowerShell 7 erreichbar ist. Windows PowerShell 5.1 mit powershell.exe ist nicht die vorgesehene Umgebung für diesen Kurs.
Wichtige PowerShell-Begriffe aus diesem Tutorial
| Begriff | Aufgabe |
|---|---|
| [switch] | Ein-/Aus-Schalter für den Testmodus. |
| Read-Host und Trim() | Eingabe lesen und äußeren Leerraum entfernen. |
| Name / BaseName | Dateiname mit oder ohne letzte Endung. |
| @(…) | Ergebnis als Array sammeln. |
| Sort-Object -Unique | Namen sortieren und gleiche Namen zusammenfassen. |
| Where-Object / $_ | Elemente anhand einer Bedingung filtern. |
| -notcontains | Prüfen, ob eine Sammlung einen Wert nicht enthält. |
| .Count | Anzahl der Elemente abfragen. |
| $PSScriptRoot | Ordner des ausgeführten PowerShell-Skripts. |
| Join-Path | Pfadbestandteile zusammensetzen. |
| Get-Date | Zeitstempel erzeugen. |
| Out-File | Ergebnisdatei speichern. |
| Set-Clipboard | Text in die Zwischenablage kopieren. |
Was haben wir in diesem Teil gelernt?
- Zwei Ordner anhand ihrer Dateinamen in beide Richtungen vergleichen.
- Zwischen vollständigem Dateinamen und Basisnamen wählen.
- Dateianzahl und eindeutige Vergleichsnamen unterscheiden.
- Den Testmodus für eine Vorschau ohne Ergebnisdateien verwenden.
- Berichte am passenden Ort als UTF-8-Dateien speichern.
- Genau zwei Ordner über Senden an übergeben.
- Beide SendTo-Berichte zusätzlich in die Zwischenablage kopieren.
- Wiederkehrende Aufgaben in kleine Funktionen auslagern.
Video zu diesem Tutorial:
Das könnte Dich auch interessieren
Keine Einträge gefunden

