PowerShell 7 Grundkurs Teil 007: Zeitstempel hinzufügen und entfernen
Worum geht es in diesem Teil?
In diesem Teil des PowerShell-7-Grundkurses versehen wir Dateinamen automatisch mit einem Zeitstempel und entfernen diesen bei Bedarf wieder.
Aus einer Datei wie:
Rechnung.pdf
wird beispielsweise:
2026-08-21_14-35-42_Rechnung.pdf

Powershell 7 Dateiname mit Zeitstempel
Das verwendete Format lautet:
JJJJ-MM-TT_HH-MM-SS_Dateiname.ext
Wir erstellen vier aufeinander abgestimmte Varianten. Zuerst verwenden wir zwei Skripte, die gemeinsam mit ihren Starter-Batchdateien direkt in den zu bearbeitenden Ordner kopiert werden. Danach folgen zwei SendTo-Varianten für das Windows-Menü Senden an.
- Zeitstempel bei Dateien im aktuellen Ordner hinzufügen
- Zeitstempel bei Dateien im aktuellen Ordner wieder entfernen
- Zeitstempel über Senden an hinzufügen
- Zeitstempel über Senden an wieder entfernen
Die Reihenfolge ist bewusst paarweise aufgebaut: Wir sehen zuerst die Anwendung zum Erstellen eines Zeitstempels und erklären danach den Code. Direkt anschließend folgt die passende Variante zum Entfernen. Danach wiederholen wir denselben Ablauf mit den beiden SendTo-Versionen.
Was ist das Ziel?
Mit einem Zeitstempel am Anfang lassen sich Dateien chronologisch sortieren und eindeutig einem bestimmten Bearbeitungszeitpunkt zuordnen. Das kann beispielsweise bei Exporten, Sicherungen, Berichten oder regelmäßig erzeugten Dateien hilfreich sein.
Da ein solcher Präfix nicht immer dauerhaft benötigt wird, gehört zu jeder Erstellen-Variante eine passende Entfernen-Variante. Beide Richtungen unterstützen einen sicheren Testmodus, prüfen mögliche Namenskonflikte und führen die eigentliche Umbenennung erst nach allen Vorprüfungen aus.
Warum ist dieser Teil wichtig?
In diesem Tutorial verbinden wir mehrere wichtige Grundlagen aus PowerShell 7:
Get-Date -Formaterzeugt einen einheitlich formatierten Zeitstempel.- Reguläre Ausdrücke erkennen einen Zeitstempel ausschließlich am Anfang eines Dateinamens.
Get-ChildItem -Fileermittelt direkt enthaltene Dateien.-containsprüft ausgeschlossene Dateiendungen.Join-Pathsetzt Ordnerpfad und neuen Dateinamen sicher zusammen.Test-Pathschützt bereits vorhandene Zieldateien.[PSCustomObject]speichert geplante Umbenennungen mit Quelle und Ziel.HashSet[string]reserviert bereits geplante Zielpfade.Rename-Itemführt die Umbenennung im Echtmodus aus.ValueFromRemainingArgumentsübernimmt bei SendTo mehrere übergebene Argumente.
Hinweis zur Kursreihe
Dieses Tutorial gehört zum PowerShell-7-Grundkurs. Der Aufbau orientiert sich an den entsprechenden Teilen für Batch und Python. Dadurch lassen sich die unterschiedlichen Schreibweisen und Möglichkeiten der drei Programmiersprachen besonders gut vergleichen.
Downloads zu diesem Teil
Dateien für PowerShell 7 Grundkurs Teil 007:
Download PowerShell 7 Grundkurs: 007_Zeitstempel_im_Dateinamen als ZIP-Datei.
Entpacken nach:
C:\TOPTORIALS_CODE\010_PowerShell_7_Grundkurs
Dadurch entsteht dieser Hauptordner:
C:\TOPTORIALS_CODE\010_PowerShell_7_Grundkurs\007_Zeitstempel_im_Dateinamen
Testumgebung zum Mitmachen
Für gefahrlose Tests kann wieder die vorbereitete Testumgebung verwendet werden.
Testumgebung für Windows-Automatisierung:Download TOPTORIALS_Testdaten_Windows_Automatisierung_V001.zip
Entpacken nach:
C:\TOPTORIALS_CODE\1000_TESTBEREICH
Für PowerShell 7 befindet sich der passende Testbereich anschließend unter:
C:\TOPTORIALS_CODE\1000_TESTBEREICH\TOPTORIALS_Testdaten_Windows_Automatisierung_PowerShell_7_V001\007_Zeitstempel_im_Dateinamen
Sicherheitshinweis
Wichtig:Teste Skripte zum Umbenennen zuerst immer mit Kopien unwichtiger Dateien. Die mitgelieferten Starter-Batchdateien enthalten im Dateinamen zunächst _test. Dadurch wird nur angezeigt und protokolliert, was das jeweilige Skript umbenennen würde.
Für den Echtmodus wird _test aus dem Namen der Starter-Batchdatei entfernt. Zusätzlich muss die Sicherheitsabfrage mit JA bestätigt werden.
Verwende bei wichtigen Dateien zusätzlich eine aktuelle Datensicherung. Die Nutzung der Skripte erfolgt auf eigene Verantwortung.
Voraussetzungen
- Windows 10 oder Windows 11
- installiertes PowerShell 7 mit dem Befehl
pwsh - Schreibrechte in den zu bearbeitenden Ordnern
- PowerShell-Skript und passende Starter-Batchdatei bleiben jeweils zusammen
Enthaltene Ordner und Dateien
007_Zeitstempel_im_Dateinamen
│
├── 01_Zeitstempel_im_Dateinamen
│ ├── 007_zeitstempel_im_dateinamen.ps1
│ └── 007_zeitstempel_im_dateinamen_starter_batch_test.bat
│
├── 02_Zeitstempel_aus_Dateinamen_entfernen
│ ├── 007_zeitstempel_aus_dateinamen_entfernen.ps1
│ └── 007_zeitstempel_aus_dateinamen_entfernen_starter_batch_test.bat
│
├── 03_SendTo_Zeitstempel_im_Dateinamen
│ ├── 007_sendto_zeitstempel_im_dateinamen.ps1
│ └── 007_sendto_zeitstempel_im_dateinamen_starter_batch_test.bat
│
└── 04_SendTo_Zeitstempel_aus_Dateinamen_entfernen
├── 007_sendto_zeitstempel_aus_dateinamen_entfernen.ps1
└── 007_sendto_zeitstempel_aus_dateinamen_entfernen_starter_batch_test.bat
Das Zeitstempelformat
Der Zeitstempel wird mit Get-Date genau einmal pro Skriptdurchlauf erzeugt:
$zeitstempel = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
Alle Dateien eines Durchlaufs erhalten damit denselben Zeitstempel. Die Sortierreihenfolge Jahr, Monat, Tag, Stunde, Minute und Sekunde sorgt dafür, dass die Dateinamen auch alphabetisch chronologisch angeordnet werden.
Das abschließende Trennzeichen wird beim Zusammensetzen ergänzt:
$neuerName = $zeitstempel + "_" + $datei.Name
Welche Dateien werden ausgelassen?
Damit die Kursdateien und mögliche Protokolle nicht selbst umbenannt werden, sind folgende Dateiendungen ausgeschlossen:
.bat, .cmd, .ps1, .py, .log
Die Verarbeitung ist außerdem nicht rekursiv. Bei einem übergebenen Ordner werden nur die Dateien verarbeitet, die direkt in diesem Ordner liegen. Inhalte weiterer Unterordner bleiben unverändert.
Testmodus und Echtmodus
Jede Starter-Batchdatei prüft ihren eigenen Dateinamen. Solange darin _test vorkommt, übergibt sie den Schalter -Test an das PowerShell-Skript.
- Mit
_test: Die geplanten Änderungen werden nur angezeigt. - Ohne
_test: Nach der Bestätigung mitJAwerden die Dateien wirklich umbenannt.
Alle gültigen Umbenennungen werden zunächst in $plaene gesammelt. Erst eine zweite Schleife zeigt diese Pläne an oder führt sie aus.
Ausgabe, Logdatei und Zwischenablage
In allen vier PowerShell-Skripten stehen dieselben vier Ausgabemöglichkeiten bereit:
- nur Bildschirmausgabe,
- Bildschirmausgabe und Logdatei,
- Bildschirmausgabe und Zwischenablage oder
- Bildschirmausgabe, Logdatei und Zwischenablage.
Die gewünschte Kombination wird mit diesen beiden Variablen eingestellt:
$logDateiErstellen = $false
$zwischenablageVerwenden = $false
Die Ausgabe einer geplanten oder ausgeführten Umbenennung verteilt Quelle und Ziel auf eigene Zeilen. Dadurch bleiben auch lange Pfade gut lesbar.
Variante 1: Zeitstempel im aktuellen Ordner erstellen
So wird die Variante angewendet
Kopiere den Inhalt des Ordners 01_Zeitstempel_im_Dateinamen in den Ordner, dessen Dateien einen Zeitstempel erhalten sollen. PowerShell-Skript und Starter-Batchdatei müssen gemeinsam dort liegen.
Mein_Arbeitsordner
├── 007_zeitstempel_im_dateinamen.ps1
├── 007_zeitstempel_im_dateinamen_starter_batch_test.bat
├── Rechnung.pdf
├── Bericht.docx
└── Foto.jpg
Starte zuerst die Datei:
007_zeitstempel_im_dateinamen_starter_batch_test.bat
Im Testmodus werden nur die geplanten Zielnamen angezeigt. Wenn die Ausgabe stimmt, entfernst du _test aus dem Dateinamen der Starter-Batchdatei und startest sie erneut. Bestätige den Echtlauf anschließend mit JA.
Danach können die Dateien beispielsweise so aussehen:
2026-08-21_14-35-42_Rechnung.pdf
2026-08-21_14-35-42_Bericht.docx
2026-08-21_14-35-42_Foto.jpg
Vollständiges PowerShell-7-Skript
# ============================================================
# TOPTORIALS OFFICE - PowerShell 7 Grundkurs
# Script: 007_zeitstempel_im_dateinamen.ps1
# Beschreibung: Fügt Dateien im aktuellen Ordner einen Zeitstempel hinzu.
# Autor: Chris
# YouTube: https://www.youtube.com/@TOPTORIALS-OFFICE
# Webseite: https://www.toptorials.com
# Version: 1.0
# Stand: 2026-08-21
# ============================================================
param (
[switch]$Test
)
Write-Host ""
$basisOrdner = (Get-Location).Path
$zeitstempel = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
$zeitstempelMuster = '^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}_'
$ausgeschlosseneEndungen = @(".bat", ".cmd", ".ps1", ".py", ".log")
# ------------------------------------------------------------
# Welche zusätzliche Ausgabe soll erstellt werden?
# Wichtig: Immer nur EINE der folgenden Varianten aktiv lassen.
# ------------------------------------------------------------
# Variante 1: Nur Bildschirmausgabe
$logDateiErstellen = $false
$zwischenablageVerwenden = $false
# Variante 2: Logdatei erstellen
# $logDateiErstellen = $true
# $zwischenablageVerwenden = $false
# Variante 3: Nur in die Zwischenablage kopieren
# $logDateiErstellen = $false
# $zwischenablageVerwenden = $true
# Variante 4: Logdatei erstellen und in die Zwischenablage kopieren
# $logDateiErstellen = $true
# $zwischenablageVerwenden = $true
# ------------------------------------------------------------
# Modus, Zähler, Protokoll und Pläne vorbereiten
# ------------------------------------------------------------
if ($Test) {
$modusText = "TESTMODUS"
}
else {
$modusText = "ECHTMODUS"
}
$anzahlUmbenannt = 0
$anzahlUebersprungen = 0
$anzahlFehler = 0
$protokoll = @()
$plaene = @()
$protokoll += "Dateien im aktuellen Ordner werden mit einem Zeitstempel umbenannt."
$protokoll += "Modus: $modusText"
$protokoll += "Ordner: $basisOrdner"
$protokoll += "Zeitstempel: $zeitstempel"
$protokoll += "Ausgeschlossene Endungen: $($ausgeschlosseneEndungen -join ', ')"
$protokoll += ""
Write-Host "Dateien im aktuellen Ordner werden mit einem Zeitstempel umbenannt..."
Write-Host ""
Write-Host "Ordner:"
Write-Host $basisOrdner
Write-Host ""
Write-Host "Zeitstempel: $zeitstempel"
Write-Host "Modus: $modusText"
Write-Host "Ausgeschlossene Endungen: $($ausgeschlosseneEndungen -join ', ')"
Write-Host ""
# ------------------------------------------------------------
# Direkt enthaltene Dateien erfassen
# Unterordner werden nicht durchsucht.
# ------------------------------------------------------------
try {
$dateien = @(Get-ChildItem -LiteralPath $basisOrdner -File -Force -ErrorAction Stop)
}
catch {
Write-Host "FEHLER: Der Ordnerinhalt konnte nicht gelesen werden. Grund: $($_.Exception.Message)"
Write-Host ""
Read-Host "Drücke Enter zum Beenden"
exit
}
# ------------------------------------------------------------
# Dateien prüfen und Umbenennungen planen
# ------------------------------------------------------------
foreach ($datei in $dateien) {
if ($ausgeschlosseneEndungen -contains $datei.Extension) {
$meldung = "ÜBERSPRUNGEN: `"$($datei.FullName)`" - Dateiendung ist ausgeschlossen"
Write-Host $meldung
$protokoll += $meldung
$anzahlUebersprungen++
continue
}
if ($datei.Name -match $zeitstempelMuster) {
$meldung = "ÜBERSPRUNGEN: `"$($datei.FullName)`" - Zeitstempel ist bereits vorhanden"
Write-Host $meldung
$protokoll += $meldung
$anzahlUebersprungen++
continue
}
$neuerName = $zeitstempel + "_" + $datei.Name
$zielPfad = Join-Path -Path $basisOrdner -ChildPath $neuerName
if (Test-Path -LiteralPath $zielPfad) {
$meldung = "ÜBERSPRUNGEN: `"$($datei.FullName)`" - Zieldatei existiert bereits: `"$zielPfad`""
Write-Host $meldung
$protokoll += $meldung
$anzahlUebersprungen++
continue
}
$plaene += [PSCustomObject]@{
Quelle = $datei.FullName
AlterName = $datei.Name
NeuerName = $neuerName
Ziel = $zielPfad
}
}
# ------------------------------------------------------------
# Sicherheitsabfrage bei der echten Ausführung
# ------------------------------------------------------------
if (-not $Test -and $plaene.Count -gt 0) {
Write-Host ""
Write-Host "ACHTUNG: Dieses Skript wird Dateien wirklich umbenennen."
Write-Host ""
$antwort = Read-Host "Zum Fortfahren JA eingeben"
if ($antwort -ne "JA") {
Write-Host ""
Write-Host "Abgebrochen."
Write-Host ""
Read-Host "Drücke Enter zum Beenden"
exit
}
Write-Host ""
}
# ------------------------------------------------------------
# Geplante Umbenennungen ausführen
# ------------------------------------------------------------
foreach ($plan in $plaene) {
if ($Test) {
$meldung = "WÜRDE UMBENENNEN:`nQuelle: `"$($plan.Quelle)`"`nZiel: `"$($plan.Ziel)`"`n---"
Write-Host $meldung
$protokoll += $meldung
$anzahlUmbenannt++
continue
}
try {
Rename-Item -LiteralPath $plan.Quelle -NewName $plan.NeuerName -ErrorAction Stop
$meldung = "UMBENANNT:`nQuelle: `"$($plan.Quelle)`"`nZiel: `"$($plan.Ziel)`"`n---"
Write-Host $meldung
$protokoll += $meldung
$anzahlUmbenannt++
}
catch {
$meldung = "FEHLER: `"$($plan.Quelle)`" konnte nicht umbenannt werden. Grund: $($_.Exception.Message)"
Write-Host $meldung
$protokoll += $meldung
$anzahlFehler++
}
}
# ------------------------------------------------------------
# Zusammenfassung
# ------------------------------------------------------------
$protokoll += ""
$protokoll += "Fertig."
Write-Host ""
Write-Host "Fertig."
Write-Host ""
if ($Test) {
$meldung1 = "Anzahl Dateien, die umbenannt würden: $anzahlUmbenannt"
$meldung2 = "Anzahl übersprungen: $anzahlUebersprungen"
$meldung3 = "Anzahl Fehler: $anzahlFehler"
Write-Host $meldung1
Write-Host $meldung2
Write-Host $meldung3
Write-Host ""
Write-Host "Es wurden keine Dateien umbenannt."
Write-Host "Wenn alles richtig aussieht, entferne _test aus dem Namen der Starter-Batchdatei."
$protokoll += $meldung1
$protokoll += $meldung2
$protokoll += $meldung3
$protokoll += "Es wurden keine Dateien umbenannt."
}
else {
$meldung1 = "Anzahl umbenannt: $anzahlUmbenannt"
$meldung2 = "Anzahl übersprungen: $anzahlUebersprungen"
$meldung3 = "Anzahl Fehler: $anzahlFehler"
Write-Host $meldung1
Write-Host $meldung2
Write-Host $meldung3
$protokoll += $meldung1
$protokoll += $meldung2
$protokoll += $meldung3
}
# ------------------------------------------------------------
# Optionale Ausgabe als Logdatei und in die Zwischenablage
# ------------------------------------------------------------
$protokollText = $protokoll -join [Environment]::NewLine
$protokollZeitstempel = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
$logDatei = Join-Path -Path $basisOrdner -ChildPath "umbenennprotokoll_zeitstempel_setzen_$protokollZeitstempel.log"
if ($logDateiErstellen) {
try {
$protokollText | Set-Content -LiteralPath $logDatei -Encoding UTF8 -ErrorAction Stop
Write-Host ""
Write-Host "Das Protokoll wurde erstellt:"
Write-Host $logDatei
}
catch {
Write-Host ""
Write-Host "FEHLER: Das Protokoll konnte nicht erstellt werden. Grund: $($_.Exception.Message)"
}
}
if ($zwischenablageVerwenden) {
try {
$protokollText | Set-Clipboard -ErrorAction Stop
Write-Host ""
Write-Host "Das Protokoll wurde zusätzlich in die Zwischenablage kopiert."
}
catch {
Write-Host ""
Write-Host "FEHLER: Das Protokoll konnte nicht in die Zwischenablage kopiert werden. Grund: $($_.Exception.Message)"
}
}
Write-Host ""
Read-Host "Drücke Enter zum Beenden"
So funktioniert die Erstellen-Variante
Die Starter-Batchdatei wechselt mit cd /d "%~dp0" zunächst in ihren eigenen Ordner. Deshalb kann das PowerShell-Skript den aktuellen Arbeitsordner mit Get-Location übernehmen:
$basisOrdner = (Get-Location).Path
Get-Date -Format "yyyy-MM-dd_HH-mm-ss" erzeugt den gemeinsamen Zeitstempel für den gesamten Durchlauf. Mit Get-ChildItem -File werden ausschließlich die direkt enthaltenen Dateien ermittelt.
Die Prüfung mit -match erkennt Dateien, die bereits mit einem passenden Zeitstempel beginnen:
$zeitstempelMuster = '^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}_'
Ein bereits vorhandener Zeitstempel wird nicht erneut vorangestellt. Auch ausgeschlossene Endungen und bereits vorhandene Zielnamen werden übersprungen.
Für jede gültige Datei entsteht ein [PSCustomObject] mit Quelle, altem Namen, neuem Namen und Zielpfad. Im Testmodus werden diese Pläne nur ausgegeben. Im Echtmodus führt Rename-Item die Umbenennung nach der Sicherheitsabfrage aus.
Starter-Batchdatei für Variante 1
@echo off
REM ============================================================
REM TOPTORIALS OFFICE - PowerShell 7 Grundkurs
REM Script: 007_zeitstempel_im_dateinamen_starter_batch_test.bat
REM Beschreibung: Startet die Variante zum Hinzufügen eines Zeitstempels.
REM Autor: Chris
REM YouTube: https://www.youtube.com/@TOPTORIALS-OFFICE
REM Webseite: https://www.toptorials.com
REM Version: 1.0
REM Stand: 2026-08-21
REM
REM Hinweis:
REM Solange _test im Dateinamen steht, wird -Test uebergeben.
REM Fuer die echte Ausfuehrung _test aus dem Dateinamen entfernen.
REM ============================================================
chcp 65001 >nul
cd /d "%~dp0"
echo %~n0 | find /i "_test" >nul
if not errorlevel 1 (
pwsh -ExecutionPolicy Bypass -File "007_zeitstempel_im_dateinamen.ps1" -Test
) else (
pwsh -ExecutionPolicy Bypass -File "007_zeitstempel_im_dateinamen.ps1"
)
%~n0 liefert den Namen der Starter-Batchdatei ohne Dateiendung. find /i "_test" prüft diesen Namen ohne Beachtung der Groß- und Kleinschreibung. Wird _test gefunden, hängt die Batchdatei das Argument -Test an den PowerShell-Aufruf an.
Variante 2: Zeitstempel im aktuellen Ordner entfernen
So wird die Variante angewendet
Kopiere jetzt den Inhalt des Ordners 02_Zeitstempel_aus_Dateinamen_entfernen in den Ordner mit den zuvor umbenannten Dateien.
Starte auch hier zuerst die Testdatei:
007_zeitstempel_aus_dateinamen_entfernen_starter_batch_test.bat
Das Skript erkennt den Zeitstempel am Anfang, entfernt ihn aus dem geplanten Zielnamen und zeigt das Ergebnis an. Für den Echtlauf entfernst du wieder _test, startest die Batchdatei erneut und bestätigst mit JA.
2026-08-21_14-35-42_Rechnung.pdf → Rechnung.pdf
2026-08-21_14-35-42_Bericht.docx → Bericht.docx
2026-08-21_14-35-42_Foto.jpg → Foto.jpg
Vollständiges PowerShell-7-Skript
# ============================================================
# TOPTORIALS OFFICE - PowerShell 7 Grundkurs
# Script: 007_zeitstempel_aus_dateinamen_entfernen.ps1
# Beschreibung: Entfernt Zeitstempel aus Dateinamen im aktuellen Ordner.
# Autor: Chris
# YouTube: https://www.youtube.com/@TOPTORIALS-OFFICE
# Webseite: https://www.toptorials.com
# Version: 1.0
# Stand: 2026-08-21
# ============================================================
param (
[switch]$Test
)
Write-Host ""
$basisOrdner = (Get-Location).Path
$zeitstempelMuster = '^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}_?'
$zeitstempelRegex = [regex]::new($zeitstempelMuster)
$ausgeschlosseneEndungen = @(".bat", ".cmd", ".ps1", ".py", ".log")
# ------------------------------------------------------------
# Welche zusätzliche Ausgabe soll erstellt werden?
# Wichtig: Immer nur EINE der folgenden Varianten aktiv lassen.
# ------------------------------------------------------------
# Variante 1: Nur Bildschirmausgabe
$logDateiErstellen = $false
$zwischenablageVerwenden = $false
# Variante 2: Logdatei erstellen
# $logDateiErstellen = $true
# $zwischenablageVerwenden = $false
# Variante 3: Nur in die Zwischenablage kopieren
# $logDateiErstellen = $false
# $zwischenablageVerwenden = $true
# Variante 4: Logdatei erstellen und in die Zwischenablage kopieren
# $logDateiErstellen = $true
# $zwischenablageVerwenden = $true
# ------------------------------------------------------------
# Freien Zielnamen ermitteln
# Bereits vorhandene und bereits geplante Ziele berücksichtigen.
# ------------------------------------------------------------
function Get-FreierZielName {
param (
[string]$Ordner,
[string]$BasisName,
[string]$Erweiterung,
[System.Collections.Generic.HashSet[string]]$ReservierteZiele
)
$zielName = $BasisName + $Erweiterung
$zielPfad = Join-Path -Path $Ordner -ChildPath $zielName
if (
-not (Test-Path -LiteralPath $zielPfad) -and
-not $ReservierteZiele.Contains($zielPfad)
) {
[void]$ReservierteZiele.Add($zielPfad)
return [PSCustomObject]@{
Name = $zielName
Pfad = $zielPfad
}
}
$nummer = 1
do {
$nummerText = $nummer.ToString("D3")
$zielName = $BasisName + "_" + $nummerText + $Erweiterung
$zielPfad = Join-Path -Path $Ordner -ChildPath $zielName
$nummer++
}
while (
(Test-Path -LiteralPath $zielPfad) -or
$ReservierteZiele.Contains($zielPfad)
)
[void]$ReservierteZiele.Add($zielPfad)
return [PSCustomObject]@{
Name = $zielName
Pfad = $zielPfad
}
}
# ------------------------------------------------------------
# Modus, Zähler, Protokoll und Pläne vorbereiten
# ------------------------------------------------------------
if ($Test) {
$modusText = "TESTMODUS"
}
else {
$modusText = "ECHTMODUS"
}
$anzahlUmbenannt = 0
$anzahlUebersprungen = 0
$anzahlFehler = 0
$protokoll = @()
$plaene = @()
$reservierteZiele = [System.Collections.Generic.HashSet[string]]::new(
[System.StringComparer]::OrdinalIgnoreCase
)
$protokoll += "Zeitstempel werden aus Dateinamen im aktuellen Ordner entfernt."
$protokoll += "Modus: $modusText"
$protokoll += "Ordner: $basisOrdner"
$protokoll += "Erkanntes Format: JJJJ-MM-TT_HH-MM-SS_"
$protokoll += "Ausgeschlossene Endungen: $($ausgeschlosseneEndungen -join ', ')"
$protokoll += ""
Write-Host "Zeitstempel werden aus Dateinamen im aktuellen Ordner entfernt..."
Write-Host ""
Write-Host "Ordner:"
Write-Host $basisOrdner
Write-Host ""
Write-Host "Modus: $modusText"
Write-Host "Erkanntes Format: JJJJ-MM-TT_HH-MM-SS_"
Write-Host "Ausgeschlossene Endungen: $($ausgeschlosseneEndungen -join ', ')"
Write-Host ""
# ------------------------------------------------------------
# Direkt enthaltene Dateien erfassen
# Unterordner werden nicht durchsucht.
# ------------------------------------------------------------
try {
$dateien = @(Get-ChildItem -LiteralPath $basisOrdner -File -Force -ErrorAction Stop)
}
catch {
Write-Host "FEHLER: Der Ordnerinhalt konnte nicht gelesen werden. Grund: $($_.Exception.Message)"
Write-Host ""
Read-Host "Drücke Enter zum Beenden"
exit
}
# ------------------------------------------------------------
# Dateien prüfen und Umbenennungen planen
# ------------------------------------------------------------
foreach ($datei in $dateien) {
if ($ausgeschlosseneEndungen -contains $datei.Extension) {
$meldung = "ÜBERSPRUNGEN: `"$($datei.FullName)`" - Dateiendung ist ausgeschlossen"
Write-Host $meldung
$protokoll += $meldung
$anzahlUebersprungen++
continue
}
if ($datei.Name -notmatch $zeitstempelMuster) {
$meldung = "ÜBERSPRUNGEN: `"$($datei.FullName)`" - kein Zeitstempel am Anfang gefunden"
Write-Host $meldung
$protokoll += $meldung
$anzahlUebersprungen++
continue
}
$basisName = $zeitstempelRegex.Replace($datei.BaseName, "", 1)
if ([string]::IsNullOrEmpty($basisName)) {
$basisName = "Unbenannt"
}
$freiesZiel = Get-FreierZielName `
-Ordner $basisOrdner `
-BasisName $basisName `
-Erweiterung $datei.Extension `
-ReservierteZiele $reservierteZiele
$plaene += [PSCustomObject]@{
Quelle = $datei.FullName
AlterName = $datei.Name
NeuerName = $freiesZiel.Name
Ziel = $freiesZiel.Pfad
}
}
# ------------------------------------------------------------
# Sicherheitsabfrage bei der echten Ausführung
# ------------------------------------------------------------
if (-not $Test -and $plaene.Count -gt 0) {
Write-Host ""
Write-Host "ACHTUNG: Dieses Skript wird Dateien wirklich umbenennen."
Write-Host ""
$antwort = Read-Host "Zum Fortfahren JA eingeben"
if ($antwort -ne "JA") {
Write-Host ""
Write-Host "Abgebrochen."
Write-Host ""
Read-Host "Drücke Enter zum Beenden"
exit
}
Write-Host ""
}
# ------------------------------------------------------------
# Geplante Umbenennungen ausführen
# ------------------------------------------------------------
foreach ($plan in $plaene) {
if ($Test) {
$meldung = "WÜRDE UMBENENNEN:`nQuelle: `"$($plan.Quelle)`"`nZiel: `"$($plan.Ziel)`"`n---"
Write-Host $meldung
$protokoll += $meldung
$anzahlUmbenannt++
continue
}
try {
Rename-Item -LiteralPath $plan.Quelle -NewName $plan.NeuerName -ErrorAction Stop
$meldung = "UMBENANNT:`nQuelle: `"$($plan.Quelle)`"`nZiel: `"$($plan.Ziel)`"`n---"
Write-Host $meldung
$protokoll += $meldung
$anzahlUmbenannt++
}
catch {
$meldung = "FEHLER: `"$($plan.Quelle)`" konnte nicht umbenannt werden. Grund: $($_.Exception.Message)"
Write-Host $meldung
$protokoll += $meldung
$anzahlFehler++
}
}
# ------------------------------------------------------------
# Zusammenfassung
# ------------------------------------------------------------
$protokoll += ""
$protokoll += "Fertig."
Write-Host ""
Write-Host "Fertig."
Write-Host ""
if ($Test) {
$meldung1 = "Anzahl Dateien, die umbenannt würden: $anzahlUmbenannt"
$meldung2 = "Anzahl übersprungen: $anzahlUebersprungen"
$meldung3 = "Anzahl Fehler: $anzahlFehler"
Write-Host $meldung1
Write-Host $meldung2
Write-Host $meldung3
Write-Host ""
Write-Host "Es wurden keine Dateien umbenannt."
Write-Host "Wenn alles richtig aussieht, entferne _test aus dem Namen der Starter-Batchdatei."
$protokoll += $meldung1
$protokoll += $meldung2
$protokoll += $meldung3
$protokoll += "Es wurden keine Dateien umbenannt."
}
else {
$meldung1 = "Anzahl umbenannt: $anzahlUmbenannt"
$meldung2 = "Anzahl übersprungen: $anzahlUebersprungen"
$meldung3 = "Anzahl Fehler: $anzahlFehler"
Write-Host $meldung1
Write-Host $meldung2
Write-Host $meldung3
$protokoll += $meldung1
$protokoll += $meldung2
$protokoll += $meldung3
}
# ------------------------------------------------------------
# Optionale Ausgabe als Logdatei und in die Zwischenablage
# ------------------------------------------------------------
$protokollText = $protokoll -join [Environment]::NewLine
$protokollZeitstempel = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
$logDatei = Join-Path -Path $basisOrdner -ChildPath "umbenennprotokoll_zeitstempel_entfernen_$protokollZeitstempel.log"
if ($logDateiErstellen) {
try {
$protokollText | Set-Content -LiteralPath $logDatei -Encoding UTF8 -ErrorAction Stop
Write-Host ""
Write-Host "Das Protokoll wurde erstellt:"
Write-Host $logDatei
}
catch {
Write-Host ""
Write-Host "FEHLER: Das Protokoll konnte nicht erstellt werden. Grund: $($_.Exception.Message)"
}
}
if ($zwischenablageVerwenden) {
try {
$protokollText | Set-Clipboard -ErrorAction Stop
Write-Host ""
Write-Host "Das Protokoll wurde zusätzlich in die Zwischenablage kopiert."
}
catch {
Write-Host ""
Write-Host "FEHLER: Das Protokoll konnte nicht in die Zwischenablage kopiert werden. Grund: $($_.Exception.Message)"
}
}
Write-Host ""
Read-Host "Drücke Enter zum Beenden"
So funktioniert die Entfernen-Variante
Das Muster für das Entfernen ist am Ende etwas flexibler. Der letzte Unterstrich ist mit _? optional:
$zeitstempelMuster = '^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}_?'
Dadurch werden sowohl 2026-08-21_14-35-42_Rechnung.pdf als auch 2026-08-21_14-35-42Rechnung.pdf erkannt. Mit [regex]::new wird aus dem Muster ein regulärer Ausdruck, dessen Methode Replace genau den ersten Treffer am Anfang des Basisnamens entfernt:
$basisName = $zeitstempelRegex.Replace($datei.BaseName, "", 1)
Die Dateiendung bleibt getrennt erhalten und wird später wieder angefügt. Sollte nach dem Entfernen kein Basisname übrig bleiben, verwendet das Skript Unbenannt.
Besonders wichtig ist die Funktion Get-FreierZielName. Existiert der ursprüngliche Name bereits, wird er nicht überschrieben. Stattdessen sucht die Funktion automatisch einen freien Namen mit einer dreistelligen Nummer:
Rechnung.pdf
Rechnung_001.pdf
Rechnung_002.pdf
Das HashSet[string] in $reservierteZiele berücksichtigt zusätzlich Namen, die während desselben Durchlaufs bereits geplant wurden. Damit können auch mehrere Quelldateien nicht versehentlich dasselbe Ziel erhalten.
Starter-Batchdatei für Variante 2
@echo off
REM ============================================================
REM TOPTORIALS OFFICE - PowerShell 7 Grundkurs
REM Script: 007_zeitstempel_aus_dateinamen_entfernen_starter_batch_test.bat
REM Beschreibung: Startet die Variante zum Entfernen eines Zeitstempels.
REM Autor: Chris
REM YouTube: https://www.youtube.com/@TOPTORIALS-OFFICE
REM Webseite: https://www.toptorials.com
REM Version: 1.0
REM Stand: 2026-08-21
REM
REM Hinweis:
REM Solange _test im Dateinamen steht, wird -Test uebergeben.
REM Fuer die echte Ausfuehrung _test aus dem Dateinamen entfernen.
REM ============================================================
chcp 65001 >nul
cd /d "%~dp0"
echo %~n0 | find /i "_test" >nul
if not errorlevel 1 (
pwsh -ExecutionPolicy Bypass -File "007_zeitstempel_aus_dateinamen_entfernen.ps1" -Test
) else (
pwsh -ExecutionPolicy Bypass -File "007_zeitstempel_aus_dateinamen_entfernen.ps1"
)
Variante 3: Zeitstempel über „Senden an“ erstellen
SendTo-Verknüpfung einrichten
- Mit Windows + R den Dialog Ausführen öffnen.
shell:sendtoeingeben und mit Enter bestätigen.- Eine Verknüpfung zur Datei
007_sendto_zeitstempel_im_dateinamen_starter_batch_test.batanlegen. - Der Verknüpfung einen verständlichen Namen geben, zum Beispiel
Zeitstempel hinzufügen - TEST.
Die Starter-Batchdatei und das PowerShell-Skript selbst bleiben gemeinsam im Ordner:
C:\TOPTORIALS_CODE\010_PowerShell_7_Grundkurs\007_Zeitstempel_im_Dateinamen\03_SendTo_Zeitstempel_im_Dateinamen
So wird die Variante angewendet
Markiere im Windows-Explorer eine oder mehrere Dateien, einen oder mehrere Ordner oder eine Mischung daraus. Öffne anschließend mit der rechten Maustaste das Kontextmenü und wähle Senden an → Zeitstempel hinzufügen – TEST.
Bei einer direkt übergebenen Datei wird genau diese Datei verarbeitet. Bei einem übergebenen Ordner verarbeitet das Skript die direkt enthaltenen Dateien. Unterordner werden nicht durchsucht.
Wenn die Testausgabe stimmt, entfernst du _test aus dem Namen der Original-Starter-Batchdatei. Passe danach den Namen der SendTo-Verknüpfung an und teste den Echtlauf zunächst mit unwichtigen Dateikopien.
Vollständiges PowerShell-7-Skript
# ============================================================
# TOPTORIALS OFFICE - PowerShell 7 Grundkurs
# Script: 007_sendto_zeitstempel_im_dateinamen.ps1
# Beschreibung: Fügt übergebenen Dateien und Dateien in übergebenen Ordnern einen Zeitstempel hinzu.
# Autor: Chris
# YouTube: https://www.youtube.com/@TOPTORIALS-OFFICE
# Webseite: https://www.toptorials.com
# Version: 1.0
# Stand: 2026-08-21
# ============================================================
param (
[switch]$Test,
[Parameter(ValueFromRemainingArguments = $true)]
[string[]]$Elemente
)
Write-Host ""
# ------------------------------------------------------------
# Prüfen, ob mindestens ein Element übergeben wurde
# ------------------------------------------------------------
if (-not $Elemente -or $Elemente.Count -eq 0) {
Write-Host "Bitte sende eine oder mehrere Dateien oder Ordner an dieses Skript."
Write-Host ""
Write-Host "Du kannst im Explorer Dateien oder Ordner markieren,"
Write-Host "rechts anklicken und anschließend 'Senden an' verwenden."
Write-Host ""
Read-Host "Drücke Enter zum Beenden"
exit
}
$zeitstempel = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
$zeitstempelMuster = '^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}_'
$ausgeschlosseneEndungen = @(".bat", ".cmd", ".ps1", ".py", ".log")
# ------------------------------------------------------------
# Welche zusätzliche Ausgabe soll erstellt werden?
# Wichtig: Immer nur EINE der folgenden Varianten aktiv lassen.
# ------------------------------------------------------------
# Variante 1: Nur Bildschirmausgabe
$logDateiErstellen = $false
$zwischenablageVerwenden = $false
# Variante 2: Logdatei erstellen
# $logDateiErstellen = $true
# $zwischenablageVerwenden = $false
# Variante 3: Nur in die Zwischenablage kopieren
# $logDateiErstellen = $false
# $zwischenablageVerwenden = $true
# Variante 4: Logdatei erstellen und in die Zwischenablage kopieren
# $logDateiErstellen = $true
# $zwischenablageVerwenden = $true
# ------------------------------------------------------------
# Modus, Zähler, Protokoll und Pläne vorbereiten
# ------------------------------------------------------------
if ($Test) {
$modusText = "TESTMODUS"
}
else {
$modusText = "ECHTMODUS"
}
$anzahlUmbenannt = 0
$anzahlUebersprungen = 0
$anzahlFehler = 0
$anzahlOrdner = 0
$anzahlEinzeldateien = 0
$protokoll = @()
$plaene = @()
$dateien = @()
$bereitsErfassteDateien = @{}
$protokoll += "Übergebene Dateien und Dateien in übergebenen Ordnern erhalten einen Zeitstempel."
$protokoll += "Modus: $modusText"
$protokoll += "Zeitstempel: $zeitstempel"
$protokoll += "Ausgeschlossene Endungen: $($ausgeschlosseneEndungen -join ', ')"
$protokoll += ""
Write-Host "Übergebene Dateien und Dateien in übergebenen Ordnern erhalten einen Zeitstempel..."
Write-Host ""
Write-Host "Zeitstempel: $zeitstempel"
Write-Host "Modus: $modusText"
Write-Host "Ausgeschlossene Endungen: $($ausgeschlosseneEndungen -join ', ')"
Write-Host ""
# ------------------------------------------------------------
# Übergebene Dateien und Ordner erfassen
# Ordnerinhalte werden nicht rekursiv durchsucht.
# ------------------------------------------------------------
$eindeutigeElemente = @($Elemente | Select-Object -Unique)
foreach ($elementPfad in $eindeutigeElemente) {
if (-not (Test-Path -LiteralPath $elementPfad)) {
$meldung = "ÜBERSPRUNGEN: `"$elementPfad`" - Datei oder Ordner wurde nicht gefunden"
Write-Host $meldung
$protokoll += $meldung
$anzahlUebersprungen++
continue
}
try {
$element = Get-Item -LiteralPath $elementPfad -Force -ErrorAction Stop
if ($element.PSIsContainer) {
if ($null -eq $element.Parent) {
$meldung = "ÜBERSPRUNGEN: Eine Laufwerkswurzel wird aus Sicherheitsgründen nicht verarbeitet: `"$($element.FullName)`""
Write-Host $meldung
$protokoll += $meldung
$anzahlUebersprungen++
continue
}
Write-Host "Ordner wird verarbeitet:"
Write-Host $element.FullName
Write-Host ""
$protokoll += "Verarbeiteter Ordner: $($element.FullName)"
$anzahlOrdner++
$ordnerDateien = @(
Get-ChildItem -LiteralPath $element.FullName -File -Force -ErrorAction Stop
)
foreach ($datei in $ordnerDateien) {
$vergleichsPfad = $datei.FullName.ToLowerInvariant()
if (-not $bereitsErfassteDateien.ContainsKey($vergleichsPfad)) {
$bereitsErfassteDateien[$vergleichsPfad] = $true
$dateien += $datei
}
}
$protokoll += ""
continue
}
$anzahlEinzeldateien++
$vergleichsPfad = $element.FullName.ToLowerInvariant()
if (-not $bereitsErfassteDateien.ContainsKey($vergleichsPfad)) {
$bereitsErfassteDateien[$vergleichsPfad] = $true
$dateien += $element
}
}
catch {
$meldung = "FEHLER: `"$elementPfad`" konnte nicht eingelesen werden. Grund: $($_.Exception.Message)"
Write-Host $meldung
$protokoll += $meldung
$anzahlFehler++
}
}
# ------------------------------------------------------------
# Dateien prüfen und Umbenennungen planen
# ------------------------------------------------------------
foreach ($datei in $dateien) {
if ($ausgeschlosseneEndungen -contains $datei.Extension) {
$meldung = "ÜBERSPRUNGEN: `"$($datei.FullName)`" - Dateiendung ist ausgeschlossen"
Write-Host $meldung
$protokoll += $meldung
$anzahlUebersprungen++
continue
}
if ($datei.Name -match $zeitstempelMuster) {
$meldung = "ÜBERSPRUNGEN: `"$($datei.FullName)`" - Zeitstempel ist bereits vorhanden"
Write-Host $meldung
$protokoll += $meldung
$anzahlUebersprungen++
continue
}
$neuerName = $zeitstempel + "_" + $datei.Name
$zielPfad = Join-Path -Path $datei.DirectoryName -ChildPath $neuerName
if (Test-Path -LiteralPath $zielPfad) {
$meldung = "ÜBERSPRUNGEN: `"$($datei.FullName)`" - Zieldatei existiert bereits: `"$zielPfad`""
Write-Host $meldung
$protokoll += $meldung
$anzahlUebersprungen++
continue
}
$plaene += [PSCustomObject]@{
Quelle = $datei.FullName
AlterName = $datei.Name
NeuerName = $neuerName
Ziel = $zielPfad
}
}
# ------------------------------------------------------------
# Sicherheitsabfrage bei der echten Ausführung
# ------------------------------------------------------------
if (-not $Test -and $plaene.Count -gt 0) {
Write-Host ""
Write-Host "ACHTUNG: Dieses Skript wird Dateien wirklich umbenennen."
Write-Host ""
$antwort = Read-Host "Zum Fortfahren JA eingeben"
if ($antwort -ne "JA") {
Write-Host ""
Write-Host "Abgebrochen."
Write-Host ""
Read-Host "Drücke Enter zum Beenden"
exit
}
Write-Host ""
}
# ------------------------------------------------------------
# Geplante Umbenennungen ausführen
# ------------------------------------------------------------
foreach ($plan in $plaene) {
if ($Test) {
$meldung = "WÜRDE UMBENENNEN:`nQuelle: `"$($plan.Quelle)`"`nZiel: `"$($plan.Ziel)`"`n---"
Write-Host $meldung
$protokoll += $meldung
$anzahlUmbenannt++
continue
}
try {
Rename-Item -LiteralPath $plan.Quelle -NewName $plan.NeuerName -ErrorAction Stop
$meldung = "UMBENANNT:`nQuelle: `"$($plan.Quelle)`"`nZiel: `"$($plan.Ziel)`"`n---"
Write-Host $meldung
$protokoll += $meldung
$anzahlUmbenannt++
}
catch {
$meldung = "FEHLER: `"$($plan.Quelle)`" konnte nicht umbenannt werden. Grund: $($_.Exception.Message)"
Write-Host $meldung
$protokoll += $meldung
$anzahlFehler++
}
}
# ------------------------------------------------------------
# Zusammenfassung
# ------------------------------------------------------------
$protokoll += ""
$protokoll += "Fertig."
Write-Host ""
Write-Host "Fertig."
Write-Host ""
$meldungDateien = "Übergebene Einzeldateien: $anzahlEinzeldateien"
$meldungOrdner = "Verarbeitete Ordner: $anzahlOrdner"
Write-Host $meldungDateien
Write-Host $meldungOrdner
$protokoll += $meldungDateien
$protokoll += $meldungOrdner
if ($Test) {
$meldung1 = "Anzahl Dateien, die umbenannt würden: $anzahlUmbenannt"
$meldung2 = "Anzahl übersprungen: $anzahlUebersprungen"
$meldung3 = "Anzahl Fehler: $anzahlFehler"
Write-Host $meldung1
Write-Host $meldung2
Write-Host $meldung3
Write-Host ""
Write-Host "Es wurden keine Dateien umbenannt."
Write-Host "Wenn alles richtig aussieht, entferne _test aus dem Namen der Starter-Batchdatei."
$protokoll += $meldung1
$protokoll += $meldung2
$protokoll += $meldung3
$protokoll += "Es wurden keine Dateien umbenannt."
}
else {
$meldung1 = "Anzahl umbenannt: $anzahlUmbenannt"
$meldung2 = "Anzahl übersprungen: $anzahlUebersprungen"
$meldung3 = "Anzahl Fehler: $anzahlFehler"
Write-Host $meldung1
Write-Host $meldung2
Write-Host $meldung3
$protokoll += $meldung1
$protokoll += $meldung2
$protokoll += $meldung3
}
# ------------------------------------------------------------
# Optionale Ausgabe als Logdatei und in die Zwischenablage
# ------------------------------------------------------------
$protokollText = $protokoll -join [Environment]::NewLine
$protokollZeitstempel = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
$logDatei = Join-Path -Path $PSScriptRoot -ChildPath "umbenennprotokoll_sendto_zeitstempel_setzen_$protokollZeitstempel.log"
if ($logDateiErstellen) {
try {
$protokollText | Set-Content -LiteralPath $logDatei -Encoding UTF8 -ErrorAction Stop
Write-Host ""
Write-Host "Das Protokoll wurde erstellt:"
Write-Host $logDatei
}
catch {
Write-Host ""
Write-Host "FEHLER: Das Protokoll konnte nicht erstellt werden. Grund: $($_.Exception.Message)"
}
}
if ($zwischenablageVerwenden) {
try {
$protokollText | Set-Clipboard -ErrorAction Stop
Write-Host ""
Write-Host "Das Protokoll wurde zusätzlich in die Zwischenablage kopiert."
}
catch {
Write-Host ""
Write-Host "FEHLER: Das Protokoll konnte nicht in die Zwischenablage kopiert werden. Grund: $($_.Exception.Message)"
}
}
Write-Host ""
Read-Host "Drücke Enter zum Beenden"
So funktioniert die SendTo-Erstellen-Variante
Der Parameterblock nimmt neben dem Schalter $Test alle weiteren Argumente in $Elemente entgegen:
param (
[switch]$Test,
[Parameter(ValueFromRemainingArguments = $true)]
[string[]]$Elemente
)
[string[]] bedeutet, dass mehrere Pfade gespeichert werden können. Die Batchdatei übergibt mit %* alle vom Explorer gelieferten Argumente.
Jeder Pfad wird mit Test-Path geprüft und anschließend mit Get-Item als Datei oder Ordner eingelesen. $element.PSIsContainer unterscheidet Ordner von einzelnen Dateien. Laufwerkswurzeln werden aus Sicherheitsgründen nicht verarbeitet.
Die Hashtable $bereitsErfassteDateien verhindert eine doppelte Verarbeitung. Das ist beispielsweise wichtig, wenn eine Datei direkt ausgewählt und gleichzeitig ihr übergeordneter Ordner übergeben wurde.
Nach dem Erfassen arbeitet die bekannte Prüf- und Planungslogik mit allen eindeutigen Dateien weiter. Jede Datei erhält den Zeitstempel in ihrem eigenen Ordner.
Starter-Batchdatei für Variante 3
@echo off
REM ============================================================
REM TOPTORIALS OFFICE - PowerShell 7 Grundkurs
REM Script: 007_sendto_zeitstempel_im_dateinamen_starter_batch_test.bat
REM Beschreibung: Startet die SendTo-Variante zum Hinzufügen eines Zeitstempels.
REM Autor: Chris
REM YouTube: https://www.youtube.com/@TOPTORIALS-OFFICE
REM Webseite: https://www.toptorials.com
REM Version: 1.0
REM Stand: 2026-08-21
REM
REM Hinweis:
REM Solange _test im Dateinamen steht, wird -Test uebergeben.
REM Fuer die echte Ausfuehrung _test aus dem Dateinamen entfernen.
REM ============================================================
chcp 65001 >nul
cd /d "%~dp0"
echo %~n0 | find /i "_test" >nul
if not errorlevel 1 (
pwsh -ExecutionPolicy Bypass -File "007_sendto_zeitstempel_im_dateinamen.ps1" -Test %*
) else (
pwsh -ExecutionPolicy Bypass -File "007_sendto_zeitstempel_im_dateinamen.ps1" %*
)
Der entscheidende Unterschied zu den ersten beiden Starter-Batchdateien ist %*. Dieser Ausdruck gibt alle an die Batchdatei übergebenen Argumente an das PowerShell-Skript weiter.
Variante 4: Zeitstempel über „Senden an“ entfernen
SendTo-Verknüpfung einrichten
Lege im mit shell:sendto geöffneten Ordner zusätzlich eine Verknüpfung zu dieser Starter-Batchdatei an:
C:\TOPTORIALS_CODE\010_PowerShell_7_Grundkurs\007_Zeitstempel_im_Dateinamen\04_SendTo_Zeitstempel_aus_Dateinamen_entfernen\007_sendto_zeitstempel_aus_dateinamen_entfernen_starter_batch_test.bat
Ein passender Name für die Verknüpfung ist beispielsweise Zeitstempel entfernen - TEST.
So wird die Variante angewendet
Markiere Dateien oder Ordner mit Zeitstempeln im Windows-Explorer. Wähle danach Rechtsklick → Senden an → Zeitstempel entfernen – TEST.
Das Skript zeigt für jede passende Datei den Namen an, der nach dem Entfernen des Zeitstempels entstehen würde. Dateien ohne erkannten Zeitstempel sowie die ausgeschlossenen Skript- und Protokolldateien werden übersprungen.
Für den Echtlauf entfernst du _test aus dem Namen der Original-Starter-Batchdatei, passt den Namen der Verknüpfung an und bestätigst die Ausführung mit JA.
Vollständiges PowerShell-7-Skript
# ============================================================
# TOPTORIALS OFFICE - PowerShell 7 Grundkurs
# Script: 007_sendto_zeitstempel_aus_dateinamen_entfernen.ps1
# Beschreibung: Entfernt Zeitstempel aus übergebenen Dateien und Dateien in übergebenen Ordnern.
# Autor: Chris
# YouTube: https://www.youtube.com/@TOPTORIALS-OFFICE
# Webseite: https://www.toptorials.com
# Version: 1.0
# Stand: 2026-08-21
# ============================================================
param (
[switch]$Test,
[Parameter(ValueFromRemainingArguments = $true)]
[string[]]$Elemente
)
Write-Host ""
# ------------------------------------------------------------
# Prüfen, ob mindestens ein Element übergeben wurde
# ------------------------------------------------------------
if (-not $Elemente -or $Elemente.Count -eq 0) {
Write-Host "Bitte sende eine oder mehrere Dateien oder Ordner an dieses Skript."
Write-Host ""
Write-Host "Du kannst im Explorer Dateien oder Ordner markieren,"
Write-Host "rechts anklicken und anschließend 'Senden an' verwenden."
Write-Host ""
Read-Host "Drücke Enter zum Beenden"
exit
}
$zeitstempelMuster = '^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}_?'
$zeitstempelRegex = [regex]::new($zeitstempelMuster)
$ausgeschlosseneEndungen = @(".bat", ".cmd", ".ps1", ".py", ".log")
# ------------------------------------------------------------
# Welche zusätzliche Ausgabe soll erstellt werden?
# Wichtig: Immer nur EINE der folgenden Varianten aktiv lassen.
# ------------------------------------------------------------
# Variante 1: Nur Bildschirmausgabe
$logDateiErstellen = $false
$zwischenablageVerwenden = $false
# Variante 2: Logdatei erstellen
# $logDateiErstellen = $true
# $zwischenablageVerwenden = $false
# Variante 3: Nur in die Zwischenablage kopieren
# $logDateiErstellen = $false
# $zwischenablageVerwenden = $true
# Variante 4: Logdatei erstellen und in die Zwischenablage kopieren
# $logDateiErstellen = $true
# $zwischenablageVerwenden = $true
# ------------------------------------------------------------
# Freien Zielnamen ermitteln
# Bereits vorhandene und bereits geplante Ziele berücksichtigen.
# ------------------------------------------------------------
function Get-FreierZielName {
param (
[string]$Ordner,
[string]$BasisName,
[string]$Erweiterung,
[System.Collections.Generic.HashSet[string]]$ReservierteZiele
)
$zielName = $BasisName + $Erweiterung
$zielPfad = Join-Path -Path $Ordner -ChildPath $zielName
if (
-not (Test-Path -LiteralPath $zielPfad) -and
-not $ReservierteZiele.Contains($zielPfad)
) {
[void]$ReservierteZiele.Add($zielPfad)
return [PSCustomObject]@{
Name = $zielName
Pfad = $zielPfad
}
}
$nummer = 1
do {
$nummerText = $nummer.ToString("D3")
$zielName = $BasisName + "_" + $nummerText + $Erweiterung
$zielPfad = Join-Path -Path $Ordner -ChildPath $zielName
$nummer++
}
while (
(Test-Path -LiteralPath $zielPfad) -or
$ReservierteZiele.Contains($zielPfad)
)
[void]$ReservierteZiele.Add($zielPfad)
return [PSCustomObject]@{
Name = $zielName
Pfad = $zielPfad
}
}
# ------------------------------------------------------------
# Modus, Zähler, Protokoll und Pläne vorbereiten
# ------------------------------------------------------------
if ($Test) {
$modusText = "TESTMODUS"
}
else {
$modusText = "ECHTMODUS"
}
$anzahlUmbenannt = 0
$anzahlUebersprungen = 0
$anzahlFehler = 0
$anzahlOrdner = 0
$anzahlEinzeldateien = 0
$protokoll = @()
$plaene = @()
$dateien = @()
$bereitsErfassteDateien = @{}
$reservierteZiele = [System.Collections.Generic.HashSet[string]]::new(
[System.StringComparer]::OrdinalIgnoreCase
)
$protokoll += "Zeitstempel werden aus übergebenen Dateien und Dateien in übergebenen Ordnern entfernt."
$protokoll += "Modus: $modusText"
$protokoll += "Erkanntes Format: JJJJ-MM-TT_HH-MM-SS_"
$protokoll += "Ausgeschlossene Endungen: $($ausgeschlosseneEndungen -join ', ')"
$protokoll += ""
Write-Host "Zeitstempel werden aus übergebenen Dateien und Dateien in übergebenen Ordnern entfernt..."
Write-Host ""
Write-Host "Modus: $modusText"
Write-Host "Erkanntes Format: JJJJ-MM-TT_HH-MM-SS_"
Write-Host "Ausgeschlossene Endungen: $($ausgeschlosseneEndungen -join ', ')"
Write-Host ""
# ------------------------------------------------------------
# Übergebene Dateien und Ordner erfassen
# Ordnerinhalte werden nicht rekursiv durchsucht.
# ------------------------------------------------------------
$eindeutigeElemente = @($Elemente | Select-Object -Unique)
foreach ($elementPfad in $eindeutigeElemente) {
if (-not (Test-Path -LiteralPath $elementPfad)) {
$meldung = "ÜBERSPRUNGEN: `"$elementPfad`" - Datei oder Ordner wurde nicht gefunden"
Write-Host $meldung
$protokoll += $meldung
$anzahlUebersprungen++
continue
}
try {
$element = Get-Item -LiteralPath $elementPfad -Force -ErrorAction Stop
if ($element.PSIsContainer) {
if ($null -eq $element.Parent) {
$meldung = "ÜBERSPRUNGEN: Eine Laufwerkswurzel wird aus Sicherheitsgründen nicht verarbeitet: `"$($element.FullName)`""
Write-Host $meldung
$protokoll += $meldung
$anzahlUebersprungen++
continue
}
Write-Host "Ordner wird verarbeitet:"
Write-Host $element.FullName
Write-Host ""
$protokoll += "Verarbeiteter Ordner: $($element.FullName)"
$anzahlOrdner++
$ordnerDateien = @(
Get-ChildItem -LiteralPath $element.FullName -File -Force -ErrorAction Stop
)
foreach ($datei in $ordnerDateien) {
$vergleichsPfad = $datei.FullName.ToLowerInvariant()
if (-not $bereitsErfassteDateien.ContainsKey($vergleichsPfad)) {
$bereitsErfassteDateien[$vergleichsPfad] = $true
$dateien += $datei
}
}
$protokoll += ""
continue
}
$anzahlEinzeldateien++
$vergleichsPfad = $element.FullName.ToLowerInvariant()
if (-not $bereitsErfassteDateien.ContainsKey($vergleichsPfad)) {
$bereitsErfassteDateien[$vergleichsPfad] = $true
$dateien += $element
}
}
catch {
$meldung = "FEHLER: `"$elementPfad`" konnte nicht eingelesen werden. Grund: $($_.Exception.Message)"
Write-Host $meldung
$protokoll += $meldung
$anzahlFehler++
}
}
# ------------------------------------------------------------
# Dateien prüfen und Umbenennungen planen
# ------------------------------------------------------------
foreach ($datei in $dateien) {
if ($ausgeschlosseneEndungen -contains $datei.Extension) {
$meldung = "ÜBERSPRUNGEN: `"$($datei.FullName)`" - Dateiendung ist ausgeschlossen"
Write-Host $meldung
$protokoll += $meldung
$anzahlUebersprungen++
continue
}
if ($datei.Name -notmatch $zeitstempelMuster) {
$meldung = "ÜBERSPRUNGEN: `"$($datei.FullName)`" - kein Zeitstempel am Anfang gefunden"
Write-Host $meldung
$protokoll += $meldung
$anzahlUebersprungen++
continue
}
$basisName = $zeitstempelRegex.Replace($datei.BaseName, "", 1)
if ([string]::IsNullOrEmpty($basisName)) {
$basisName = "Unbenannt"
}
$freiesZiel = Get-FreierZielName `
-Ordner $datei.DirectoryName `
-BasisName $basisName `
-Erweiterung $datei.Extension `
-ReservierteZiele $reservierteZiele
$plaene += [PSCustomObject]@{
Quelle = $datei.FullName
AlterName = $datei.Name
NeuerName = $freiesZiel.Name
Ziel = $freiesZiel.Pfad
}
}
# ------------------------------------------------------------
# Sicherheitsabfrage bei der echten Ausführung
# ------------------------------------------------------------
if (-not $Test -and $plaene.Count -gt 0) {
Write-Host ""
Write-Host "ACHTUNG: Dieses Skript wird Dateien wirklich umbenennen."
Write-Host ""
$antwort = Read-Host "Zum Fortfahren JA eingeben"
if ($antwort -ne "JA") {
Write-Host ""
Write-Host "Abgebrochen."
Write-Host ""
Read-Host "Drücke Enter zum Beenden"
exit
}
Write-Host ""
}
# ------------------------------------------------------------
# Geplante Umbenennungen ausführen
# ------------------------------------------------------------
foreach ($plan in $plaene) {
if ($Test) {
$meldung = "WÜRDE UMBENENNEN:`nQuelle: `"$($plan.Quelle)`"`nZiel: `"$($plan.Ziel)`"`n---"
Write-Host $meldung
$protokoll += $meldung
$anzahlUmbenannt++
continue
}
try {
Rename-Item -LiteralPath $plan.Quelle -NewName $plan.NeuerName -ErrorAction Stop
$meldung = "UMBENANNT:`nQuelle: `"$($plan.Quelle)`"`nZiel: `"$($plan.Ziel)`"`n---"
Write-Host $meldung
$protokoll += $meldung
$anzahlUmbenannt++
}
catch {
$meldung = "FEHLER: `"$($plan.Quelle)`" konnte nicht umbenannt werden. Grund: $($_.Exception.Message)"
Write-Host $meldung
$protokoll += $meldung
$anzahlFehler++
}
}
# ------------------------------------------------------------
# Zusammenfassung
# ------------------------------------------------------------
$protokoll += ""
$protokoll += "Fertig."
Write-Host ""
Write-Host "Fertig."
Write-Host ""
$meldungDateien = "Übergebene Einzeldateien: $anzahlEinzeldateien"
$meldungOrdner = "Verarbeitete Ordner: $anzahlOrdner"
Write-Host $meldungDateien
Write-Host $meldungOrdner
$protokoll += $meldungDateien
$protokoll += $meldungOrdner
if ($Test) {
$meldung1 = "Anzahl Dateien, die umbenannt würden: $anzahlUmbenannt"
$meldung2 = "Anzahl übersprungen: $anzahlUebersprungen"
$meldung3 = "Anzahl Fehler: $anzahlFehler"
Write-Host $meldung1
Write-Host $meldung2
Write-Host $meldung3
Write-Host ""
Write-Host "Es wurden keine Dateien umbenannt."
Write-Host "Wenn alles richtig aussieht, entferne _test aus dem Namen der Starter-Batchdatei."
$protokoll += $meldung1
$protokoll += $meldung2
$protokoll += $meldung3
$protokoll += "Es wurden keine Dateien umbenannt."
}
else {
$meldung1 = "Anzahl umbenannt: $anzahlUmbenannt"
$meldung2 = "Anzahl übersprungen: $anzahlUebersprungen"
$meldung3 = "Anzahl Fehler: $anzahlFehler"
Write-Host $meldung1
Write-Host $meldung2
Write-Host $meldung3
$protokoll += $meldung1
$protokoll += $meldung2
$protokoll += $meldung3
}
# ------------------------------------------------------------
# Optionale Ausgabe als Logdatei und in die Zwischenablage
# ------------------------------------------------------------
$protokollText = $protokoll -join [Environment]::NewLine
$protokollZeitstempel = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
$logDatei = Join-Path -Path $PSScriptRoot -ChildPath "umbenennprotokoll_sendto_zeitstempel_entfernen_$protokollZeitstempel.log"
if ($logDateiErstellen) {
try {
$protokollText | Set-Content -LiteralPath $logDatei -Encoding UTF8 -ErrorAction Stop
Write-Host ""
Write-Host "Das Protokoll wurde erstellt:"
Write-Host $logDatei
}
catch {
Write-Host ""
Write-Host "FEHLER: Das Protokoll konnte nicht erstellt werden. Grund: $($_.Exception.Message)"
}
}
if ($zwischenablageVerwenden) {
try {
$protokollText | Set-Clipboard -ErrorAction Stop
Write-Host ""
Write-Host "Das Protokoll wurde zusätzlich in die Zwischenablage kopiert."
}
catch {
Write-Host ""
Write-Host "FEHLER: Das Protokoll konnte nicht in die Zwischenablage kopiert werden. Grund: $($_.Exception.Message)"
}
}
Write-Host ""
Read-Host "Drücke Enter zum Beenden"
So funktioniert die SendTo-Entfernen-Variante
Diese Variante verbindet die Argumentverarbeitung der SendTo-Erstellen-Version mit der Funktion Get-FreierZielName aus der zweiten Variante.
Zuerst werden alle übergebenen Dateien und die direkt enthaltenen Dateien übergebener Ordner eindeutig erfasst. Danach prüft der reguläre Ausdruck, ob der jeweilige Dateiname mit einem passenden Zeitstempel beginnt.
Der Zeitstempel wird nur aus $datei.BaseName entfernt. Die ursprüngliche Dateiendung aus $datei.Extension bleibt erhalten. Get-FreierZielName sucht anschließend im jeweiligen $datei.DirectoryName nach einem freien Ziel.
Weil ein gemeinsames HashSet[string] alle geplanten Zielpfade speichert, funktioniert der Schutz auch dann, wenn gleichzeitig Dateien aus mehreren unterschiedlichen Ordnern verarbeitet werden.
Starter-Batchdatei für Variante 4
@echo off
REM ============================================================
REM TOPTORIALS OFFICE - PowerShell 7 Grundkurs
REM Script: 007_sendto_zeitstempel_aus_dateinamen_entfernen_starter_batch_test.bat
REM Beschreibung: Startet die SendTo-Variante zum Entfernen eines Zeitstempels.
REM Autor: Chris
REM YouTube: https://www.youtube.com/@TOPTORIALS-OFFICE
REM Webseite: https://www.toptorials.com
REM Version: 1.0
REM Stand: 2026-08-21
REM
REM Hinweis:
REM Solange _test im Dateinamen steht, wird -Test uebergeben.
REM Fuer die echte Ausfuehrung _test aus dem Dateinamen entfernen.
REM ============================================================
chcp 65001 >nul
cd /d "%~dp0"
echo %~n0 | find /i "_test" >nul
if not errorlevel 1 (
pwsh -ExecutionPolicy Bypass -File "007_sendto_zeitstempel_aus_dateinamen_entfernen.ps1" -Test %*
) else (
pwsh -ExecutionPolicy Bypass -File "007_sendto_zeitstempel_aus_dateinamen_entfernen.ps1" %*
)
Wo werden die Protokolle gespeichert?
Bei den beiden Varianten für den aktuellen Ordner wird die Logdatei direkt im bearbeiteten Ordner gespeichert. Bei den beiden SendTo-Varianten liegt sie im Ordner des jeweiligen PowerShell-Skripts.
Die Protokolldateien erhalten selbst einen Zeitstempel, zum Beispiel:
umbenennprotokoll_zeitstempel_setzen_2026-08-21_14-40-05.log
umbenennprotokoll_zeitstempel_entfernen_2026-08-21_14-42-17.log
umbenennprotokoll_sendto_zeitstempel_setzen_2026-08-21_14-45-03.log
umbenennprotokoll_sendto_zeitstempel_entfernen_2026-08-21_14-47-26.log
Die Endung .log ist von der Verarbeitung ausgeschlossen. Dadurch wird auch eine bereits vorhandene Protokolldatei nicht als normale Zieldatei umbenannt.
Typische Meldungen
Datei würde umbenannt
WÜRDE UMBENENNEN:
Quelle: "C:\Daten\Rechnung.pdf"
Ziel: "C:\Daten\2026-08-21_14-35-42_Rechnung.pdf"
---
Datei wurde umbenannt
UMBENANNT:
Quelle: "C:\Daten\2026-08-21_14-35-42_Rechnung.pdf"
Ziel: "C:\Daten\Rechnung.pdf"
---
Zeitstempel ist bereits vorhanden
ÜBERSPRUNGEN: "C:\Daten\2026-08-21_14-35-42_Rechnung.pdf" - Zeitstempel ist bereits vorhanden
Kein Zeitstempel am Anfang gefunden
ÜBERSPRUNGEN: "C:\Daten\Rechnung.pdf" - kein Zeitstempel am Anfang gefunden
Dateiendung ist ausgeschlossen
ÜBERSPRUNGEN: "C:\Daten\Hilfsskript.ps1" - Dateiendung ist ausgeschlossen
Typische Fehler und mögliche Ursachen
PowerShell 7 wurde nicht gefunden
Die Starter-Batchdateien verwenden pwsh. Ist PowerShell 7 nicht installiert oder nicht über die Umgebungsvariable PATH erreichbar, kann das Skript nicht gestartet werden.
Das PowerShell-Skript wird nicht gefunden
Das PowerShell-Skript und seine passende Starter-Batchdatei müssen gemeinsam im vorgesehenen Ordner liegen. Auch die Dateinamen müssen unverändert zueinander passen.
Es werden keine Dateien gefunden
Die Skripte arbeiten nicht rekursiv. Dateien in tieferen Unterordnern werden absichtlich nicht erfasst.
Eine Datei wird übersprungen
Mögliche Gründe sind eine ausgeschlossene Dateiendung, ein bereits vorhandener Zeitstempel, ein fehlender Zeitstempel bei der Entfernen-Variante oder ein bereits vorhandener Zielname.
Eine Datei kann nicht umbenannt werden
Mögliche Ursachen sind fehlende Zugriffsrechte, eine in einem anderen Programm geöffnete Datei oder ein schreibgeschützter Datenträger.
Eine SendTo-Auswahl wird doppelt übergeben
Das Skript entfernt doppelte Pfade und führt zusätzlich eine Liste bereits erfasster Dateien. Eine Datei wird daher auch dann nur einmal geplant, wenn sie direkt und gleichzeitig über ihren Ordner in der Auswahl enthalten war.
Wichtige PowerShell-Begriffe aus diesem Tutorial
Get-Date -Format- Erzeugt Datum und Uhrzeit in einem festgelegten Textformat.
Get-Location- Liefert den aktuellen Arbeitsordner. Die normalen Varianten nutzen diesen als zu bearbeitenden Ordner.
$PSScriptRoot- Liefert den Ordner des PowerShell-Skripts. Die SendTo-Varianten verwenden ihn als Speicherort für mögliche Logdateien.
Get-ChildItem -File- Ermittelt Dateien. Ohne
-Recursewerden weitere Unterordner nicht durchsucht. -LiteralPath- Behandelt einen Pfad wörtlich, sodass besondere Zeichen im Dateinamen nicht als Platzhalter interpretiert werden.
-matchund-notmatch- Prüfen, ob ein Text zu einem regulären Ausdruck passt oder nicht passt.
^- Markiert in einem regulären Ausdruck den Anfang eines Textes. Der Zeitstempel wird deshalb nur am Anfang des Dateinamens erkannt.
\d{4}- Steht für genau vier Ziffern. Entsprechend steht
\d{2}für genau zwei Ziffern. ?- Macht das unmittelbar davorstehende Zeichen im regulären Ausdruck optional. Hier betrifft das den Unterstrich nach der Sekundenangabe.
[regex]::new- Erstellt aus einem Muster ein Objekt für reguläre Ausdrücke.
Replace- Ersetzt einen gefundenen Text. Hier wird der erkannte Zeitstempel durch einen leeren Text ersetzt.
[string]::IsNullOrEmpty- Prüft, ob ein Text leer ist oder keinen Wert enthält.
HashSet[string]- Speichert eindeutige Texte. Hier werden damit bereits geplante Zielpfade reserviert.
ToString("D3")- Formatiert eine Zahl dreistellig mit führenden Nullen, zum Beispiel
001. Test-Path- Prüft, ob eine Datei, ein Ordner oder ein geplanter Zielpfad bereits existiert.
Join-Path- Setzt einen Ordnerpfad und einen Dateinamen korrekt zusammen.
[PSCustomObject]- Erstellt ein übersichtliches Objekt mit selbst gewählten Eigenschaften. Hier speichert es die Daten einer geplanten Umbenennung.
Rename-Item- Benennt eine Datei oder einen Ordner um.
ValueFromRemainingArguments- Sammelt alle noch nicht zugeordneten Argumente des Aufrufs in einem Parameter.
[string[]]- Kennzeichnet ein Array, das mehrere Zeichenketten und damit mehrere übergebene Pfade aufnehmen kann.
PSIsContainer- Zeigt an, ob ein eingelesenes Element ein Ordner ist.
ToLowerInvariant- Erzeugt für die Dublettenprüfung eine kleingeschriebene, sprachunabhängige Vergleichsform des vollständigen Pfades.
tryundcatch- Fangen auftretende Fehler kontrolliert ab und ermöglichen verständliche Fehlermeldungen.
Set-Clipboard- Kopiert die gesammelte Ausgabe in die Windows-Zwischenablage.
`n- Erzeugt innerhalb eines PowerShell-Textes einen Zeilenumbruch.
Wichtige Batch-Begriffe aus diesem Tutorial
%~dp0- Liefert Laufwerk und Ordner der aktuell ausgeführten Batchdatei.
%~n0- Liefert den Namen der Batchdatei ohne Pfad und Dateiendung.
%*- Enthält alle Argumente, die an die Batchdatei übergeben wurden.
find /i- Sucht ohne Beachtung der Groß- und Kleinschreibung nach einem Text. Hier wird damit
_testim Namen der Starter-Batchdatei erkannt. errorlevel- Enthält den Rückgabewert des zuletzt ausgeführten Programms oder Befehls.
Was haben wir in diesem Teil gelernt?
Mit Get-Date -Format "yyyy-MM-dd_HH-mm-ss" erzeugen wir einen gut sortierbaren Zeitstempel für Dateinamen.
Ein regulärer Ausdruck erkennt, ob ein Zeitstempel bereits vorhanden ist. Die Entfernen-Varianten verwenden dasselbe Grundmuster, um den Präfix gezielt aus dem Basisnamen zu löschen.
Die Funktion Get-FreierZielName schützt vorhandene Dateien und vergibt bei Bedarf Namen wie _001, _002 und so weiter. Zusätzlich verhindert ein HashSet[string] Konflikte zwischen mehreren geplanten Zielen.
Die ersten beiden Varianten werden direkt in den zu bearbeitenden Ordner kopiert. Die beiden SendTo-Varianten übernehmen dagegen einzelne Dateien, Ordner oder gemischte Auswahlen als Argumente aus dem Windows-Explorer.
Alle vier Skripte arbeiten nicht rekursiv, lassen bestimmte Skript- und Protokolldateien aus und unterstützen Testmodus, Sicherheitsabfrage, Logdatei und Zwischenablage.
Damit haben wir für beide Arbeitsweisen einen vollständigen Ablauf: Zeitstempel hinzufügen, Ergebnis prüfen und den Zeitstempel bei Bedarf wieder sicher entfernen.
Video zu diesem Tutorial:
Das könnte Dich auch interessieren
Keine Einträge gefunden

