
aksonsat - stock.adobe.com
So kopieren Sie Dateien in PowerShell vom Quell- zum Zielordner
PowerShell automatisiert Dateiübertragungen lokal und remote. Parameter wie Filter, Include, Recurse und WhatIf ermöglichen gezielte und nachvollziehbare Kopiervorgänge.
Das Kopieren von Dateien zwischen Ordnern, Laufwerken und Computern kann sehr zeitaufwendig sein, wenn Sie dies regelmäßig manuell durchführen. Mit ein wenig PowerShell-Know-how lässt sich dieser mühsame Vorgang automatisieren und sogar komplexeste Situationen bewältigen.
Sobald Sie die mit dem Befehl Copy-Item verbundenen Parameter und deren Zusammenspiel verstanden haben, können Sie umfassende Skripte mit erweiterten PowerShell-Befehlen zum Kopieren von Dateien und Verzeichnissen erstellen.
Die Beispiele in diesem Artikel funktionieren sowohl unter Windows PowerShell als auch unter PowerShell 7.
PowerShell verfügt über Provider – .NET-Programme, die die Daten in einem Datenspeicher zur Anzeige und Bearbeitung bereitstellen – und eine Reihe von generischen Cmdlets, die provider-übergreifend funktionieren.
Dazu gehören die folgenden Cmdlets:
- *-Item
- *-ItemProperty
- *-Content
- *-Path
- *-Location
Mit einer Standardinstallation von PowerShell oder Windows PowerShell können Sie das Cmdlet Copy-Item zum Kopieren von Dateien, Registrierungsschlüsseln und Variablen verwenden. Dies wird durch das Provider Feature erleichtert, die die Interaktion mit verschiedenen Inhaltstypen mit demselben Befehl ermöglicht. Einige Module enthalten benutzerdefinierte Provider, beispielsweise das AD-Modul, mit denen Sie diese generischen Cmdlets in den von ihnen bereitgestellten AD-Daten verwenden können. Führen Sie den folgenden Befehl aus, um die PowerShell-Provider in Ihrer PowerShell-Sitzung anzuzeigen:
Get-PsProvider
Dies sind beispielsweise die Provider, die in der PowerShell-7-Sitzung auf meinem Windows-11-Computer verfügbar sind.

Wie verwenden Sie den Befehl Copy-Item?
Die einfachste Form von Copy-Item umfasst einen Quellpfad und einen Zielpfad. Um den Dateisystem-Provider zu verwenden, geben Sie die Pfade an, indem Sie unter Windows mit einem Laufwerksbuchstaben und einem Doppelpunkt und unter Linux mit einem Schrägstrich beginnen.
Wenn Sie .\ oder ./ verwenden, um das aktuelle Verzeichnis darzustellen, wird der aktuelle Pfad basierend auf dem aktuellen Arbeitsverzeichnis abgeleitet, das kein Dateisystem-Providfer-Pfad sein muss. Sie können Ihr aktuelles Arbeitsverzeichnis jederzeit mit dem Befehl Get-Location überprüfen.
Das Beispiel im folgenden PowerShell-Befehl kopiert eine einzelne Datei, die sich im Parameter Path befindet, an den im Parameter Destination angegebenen Speicherort:
Copy-Item -Path C:\source\path\file.txt -Destination D:\dest\path\text.txt
Um einen kürzeren Befehl zu verwenden, bietet PowerShell mehrere Aliase für seine wichtigsten Cmdlets. Der folgende Befehl zeigt die drei Aliase – copy, cp und cpi – für das Cmdlet Copy-Item:
Get-Alias -Definition Copy-Item

In PowerShell unter Linux gibt es den Alias cp nicht, da es bereits einen Linux-Befehl namens cp gibt.
Wie können Sie PowerShell-Befehle zum Kopieren von Dateien verwenden?
Um die Funktionsweise der verschiedenen Copy-Item-Parameter zu veranschaulichen, erstellen Sie mit dem folgenden Befehl eine Testdatei:
Get-Process | Out-File -FilePath c:\test\p1.txt
Verwenden Sie diesen Befehl, um eine Datei mit dem Parameter Destination zu kopieren. Im Parameter Destination geben Sie keinen Dateinamen an. In diesem Fall wird der ursprüngliche Dateiname p1.txt verwendet:
Copy-Item -Path C:\test\p1.txt -Destination C:\test2\
Der Befehl Copy-Item zeigt keine Meldung oder Bestätigung an, wenn ein Kopiervorgang erfolgreich war, was für neue Benutzer verwirrend sein kann.

Um sowohl den Alias als auch die Positionsparameter des Befehls zu nutzen, geben Sie die Quelle und das Ziel in der richtigen Reihenfolge an:
Copy C:\test\p1.txt C:\test2\
Die Verwendung von Aliasnamen in gespeicherten Skripten ist keine bewährte Vorgehensweise und sollte daher vermieden werden.
Um Feedback von Copy-Item zu erhalten, verwenden Sie den Parameter PassThru. Diese Funktion gibt Objekte für jedes der kopierten Elemente zurück. Dies ist ein hilfreiches Tool, um zu überprüfen, ob der Befehl ordnungsgemäß ausgeführt wurde:
Copy-Item -Path C:\test\p1.txt -Destination C:\test2\ -PassThru

Eine weitere Möglichkeit, die Ergebnisse des Befehls Copy-Item anzuzeigen, ist die Verwendung des Parameters Verbose:
Copy-Item -Path C:\test\p1.txt -Destination C:\test2\ -Verbose

Der Parameter Verbose zeigt Informationen während der Ausführung des Befehls an, während der Parameter PassThru das resultierende Dateiobjekt angibt.
Standardmäßig überschreibt PowerShell die Datei, wenn im Zielordner eine Datei mit demselben Namen vorhanden ist. Wenn die Datei im Zielverzeichnis schreibgeschützt ist, wird eine Fehlermeldung angezeigt:
Copy-Item -Path C:\test\p1.txt -Destination C:\test2\

Um diesen Fehler zu vermeiden, verwenden Sie den Parameter Force:
Copy-Item -Path C:\test\p1.txt -Destination C:\test2\ -Force
PowerShell kann Dateien im Rahmen des Kopiervorgangs umbenennen. Mit diesem Code werden beispielsweise neun Kopien der Datei p1.txt mit den Namen p2.txt bis p10.txt erstellt:
2..10 | Foreach-Object {
$newname = "p$_.txt"
Copy-Item -Path C:\test\p1.txt -Destination C:\test2\$newname
Verbose
}

In diesem Fall erstellt der Operator .. ein Array von Ganzzahlen von 2 bis 10. Anschließend erstellt der Code für jede dieser Ganzzahlen eine Datei mit dem neuen Namen.
Verwenden von PowerShell-Befehlen zum Kopieren mehrerer Dateien oder Ordner
Es gibt mehrere Techniken, um mehrere Dateien oder Ordner mit PowerShell zu kopieren:
Copy-Item -Path C:\test\*.txt -Destination C:\test2\
Copy-Item -Path C:\test\* -Filter *.txt -Destination C:\test2\
Copy-Item -Path C:\test\* -Include *.txt -Destination C:\test2\
Diese Befehle kopieren alle .txt-Dateien aus dem Ordner test in den Ordner test2, aber mit dem Parameter Include kann PowerShell selektiver vorgehen. Dieser Befehl kopiert beispielsweise nur Dateien, deren Name eine 6 enthält:
Copy-Item -Path C:\test\* -Include *6*.txt -Destination C:\test2\ -PassThru

Copy-Item verfügt über einen Parameter Exclude, mit dem bestimmte Dateien vom Kopiervorgang ausgeschlossen werden können. Dieser PowerShell-Befehl kopiert nur Textdateien, deren Name mit dem Buchstaben p beginnt, sofern der Name nicht die Ziffer 7 enthält:
Copy-Item -Path C:\test\* -Filter p*.txt -Exclude *7*.txt -Destination C:\test2\ -PassThru

Verwendung der Parameter Path, Filter, Include und Exclude
Durch die Kombination der Parameter Path, Filter, Include oder Exclude lässt sich der Kopiervorgang noch weiter verfeinern. Wenn Sie jedoch Include und Exclude im selben Aufruf verwenden, wird Exclude nach den Einschlüssen angewendet.
Kombinieren Sie beispielsweise Path, Filter, Include und Exclude. In diesem Beispiel wählt der Parameter Path alle Dateien in C:\test aus, der Parameter Filter findet alle Dateien, die mit dem Buchstaben p beginnen, der Parameter Include gibt nur .txt-Dateien aus dieser Auswahl an und der Parameter Exclude entfernt Dateien, deren Name die Ziffer 7 enthält:
Copy-Item -Path C:\test\* -Filter p* -Include *.txt -Exclude *7* -Destination C:\test2\ -PassThru

Sie können auch ein Array von Dateinamen angeben. Der Pfad wird vereinfacht, wenn Ihr Arbeitsordner der Quellordner für die Kopie ist:
Copy-Item -Path p1.txt,p3.txt,p5.txt -Destination C:\test2\
Der Parameter Path akzeptiert auch Pipeline-Eingaben. Im folgenden Beispiel überprüft PowerShell die Dateien p*.txt im Ordner C:\test, um festzustellen, ob das zweite Zeichen durch zwei teilbar ist. Ist dies der Fall, kopiert PowerShell die Datei in den Ordner C:\test2:
Get-ChildItem -Path C:\test\p*.txt | Where-Object
{(($_.BaseName).Substring(1,1) % 2 ) -eq 0} |
Copy-Item -Destination C:\test2\
Wenn Sie einen Ordner- oder Dateinamen erhalten, der Sonderzeichen enthält (*, [, ], ?), verwenden Sie anstelle des Parameters Path den Parameter LiteralPath. LiteralPath interpretiert keine Platzhalterzeichen und gibt den genauen Pfad zu einem Element an.
So testen Sie die Parameter Filter, Include und Exclude
Wenn Sie eine komplexe Kombination aus Filter, Include und Exclude verwenden, ist es möglicherweise schwer vorherzusagen, welche Dateien PowerShell kopiert. Um einen Befehl Copy-File vor der Ausführung zu testen, hängen Sie den Parameter WhatIf an jeden Befehl Copy-File an. PowerShell gibt eine Beschreibung des Vorgangs aus, anstatt die Aktion auszuführen:
Copy-Item -Path C:\test\* -Filter p* -Include *.txt -Exclude *7* -Destination C:\test2\ -PassThru -WhatIf

Eine weitere Methode zum Ausgeben der Dateien ist die Verwendung von Get-ChildItem, das dieselben Parameter Path, Filter, Include und Exclude verwendet. Sie funktionieren genauso wie bei Copy-Item. Verwenden Sie dieselben Parameter, entfernen Sie Destination, und wenden Sie sie auf Get-ChildItem an. Der Befehl gibt eine Liste der Datei- und Ordnerobjekte aus, die mit dem Buchstaben p beginnen und die Erweiterung .txt haben, und entfernt alle Dateien, deren Name die Ziffer 7 enthält:
Get-ChildItem -Path C:\test\* -Filter p* -Include *.txt -Exclude *7*

Da der Befehl die Dateien in einem Array zurückgibt, können Sie anschließend mit den Dateiobjekten arbeiten und unter anderem einen Bericht über die zu kopierenden Dateien erstellen.
So führen Sie eine rekursive Kopie durch
Um einen Ordner und seinen gesamten Inhalt zu kopieren, verwenden Sie den Parameter Recurse:
Copy-Item -Path c:\test\ -Destination c:\test2\ -Recurse
Eine rekursive Kopie durchläuft alle Unterordner unterhalb des Ordners C:\test. PowerShell erstellt dann einen Ordner mit dem Namen test im Zielordner und kopiert den Inhalt von C:\test dorthin.
Beim Kopieren zwischen Computern können Sie Universal-Naming-Convention-Pfade verwenden, um den lokalen Computer zu umgehen:
Copy-Item -Path \\server1\fs1\test\p1.txt -Destination \\server2\arc\test\
Eine weitere Möglichkeit besteht darin, PowerShell-Befehle zum Kopieren von Dateien über eine Remoting-Sitzung zu verwenden. Der folgende Befehl fordert den Benutzer zur Eingabe des Kennworts für das Administratorkonto auf dem Remote-Computer mit dem Namen W16ND01 auf. Das Sitzungsobjekt wird in der Variablen $s gespeichert, die in nachfolgenden Befehlen verwendet werden kann, um Vorgänge auf W16ND01 auszuführen:
$cred = Get-Credential -Credential W16ND01\Administrator
$s = New-PSSession -VMName W16ND01 -Credential $cred
Verwenden Sie in diesem Fall PowerShell Direct, um eine Verbindung zum Remote-Computer herzustellen. Sie müssen das Hyper-V-Modul geladen haben, um die Remote-Sitzung über VMBus erstellen zu können. Verwenden Sie anschließend die folgenden PowerShell-Befehle, um Dateien auf den Remote-Computer zu kopieren:
Copy-Item -Path c:\test\ -Destination c:\ -Recurse -ToSession $s
Sie können auch Dateien vom Remote-Computer kopieren:
Copy-Item -Path c:\test\p*.txt -Destination c:\test3\ -FromSession $s
Die Parameter ToSession und FromSession steuern die Richtung der Kopie und ob sich die Quelle und das Ziel auf dem lokalen Computer oder einem Remote-Computer befinden. Zum Senden von Daten an einen Remote-Computer wird ToSession verwendet, zum Empfangen von Dateien von einem Remote-Computer FromSession.
Leider können ToSession und FromSession nicht im selben Befehl verwendet werden, und relative Pfade werden ebenfalls nicht unterstützt. Um etwas aus dem Home-Verzeichnis Ihres Benutzerkontos auf einem Server auf einen anderen zu kopieren, während Sie über PowerShell-Remoting mit beiden Servern verbunden sind, müssen Sie bei der Angabe der vollständig qualifizierten Pfade kreativ werden.
Im folgenden Beispiel wird die Remote-Datei von Server1 lokal kopiert und dann auf Server2 kopiert:
$server1 = New-PSSession -ComputerName server1.domain.com -Credential
$cred
$server2 = New-PSSession -ComputerName server2.domain.com -Credential
$cred
$path = ‚C:\Users\user\Downloads\file.zip‘
Copy-Item -Path $path -Destination .\file.zip -FromSession $server1
Copy-Item -Path .\file.zip -Destination $path -ToSession $server2
So verfolgen Sie den Fortschritt eines Kopierbefehls
Eine nützliche Ergänzung zu Copy-Item ist die Einführung einer Fortschrittsanzeige in PowerShell 7.4. Diese Funktion zeigt den Status eines ausgeführten Befehls visuell an und hilft dem Benutzer, die verbleibende Dauer des Vorgangs abzuschätzen. Dies wird in Windows PowerShell nicht unterstützt.
Der folgende PowerShell-Code kopiert Dateien aus dem Ordner C:\PowerShell und dessen Unterordnern in den Ordner D:\PowerShell:
Copy-Item C:\PowerShell\ D:\PowerShell\ -Recurse

Die Ausgabe zeigt den Gesamtfortschritt des Kopiervorgangs in Form der kopierten Dateien, der übertragenen Gesamtdatenmenge und der aktuellen Datenübertragungsrate.
PowerShell hat außerdem den gemeinsamen Parameter ProgressAction eingeführt, mit dem die Fortschrittsanzeige deaktiviert werden kann, wenn es auf Geschwindigkeit ankommt:
Copy-Item C:\PowerShell\ D:\PowerShell\ -Recurse -ProgressAction SilentlyContinue
So kopieren Sie Dateien auf mehrere Computer
Manchmal muss eine Datei, wie eine Konfigurationsdatei, auf mehrere Remote-Server oder Clients kopiert werden. Dies ist ganz einfach, wenn auf den Computern PowerShell-Remoting aktiviert ist.
Importieren Sie zunächst die Liste der Computernamen. In diesem Beispiel wird davon ausgegangen, dass sich eine Liste mit Namen in einer Textdatei befindet, diese kann jedoch auch aus einer AD-Abfrage oder einer anderen Quelle stammen:
$remoteTargets = Get-Content .\names.txt
Speichern Sie anschließend die Anmeldeinformationen in einer Variablen:
$cred = Get-Credential
Verwenden Sie anschließend eine Foreach-Object-Schleife, um die Vorteile des Multithreadings in PowerShell 7 mit dem Parameter Parallel zu nutzen, um ein Sitzungsobjekt zu erstellen, die Datei (eine config.json-Datei) auf das Gerät zu kopieren und die Sitzung zu schließen:
$remoteTargets | Foreach-Object -Parallel {
$session = New-PSSession -ComputerName $_ -Credential $using:cred
Copy-Item -Path .\config.json -Destination
C:\ProgramData\app\config.json -ToSession $session
Remove-PsSession $session
}
Beachten Sie, wie der Code die Syntax $using: verwendet, um die Variable $cred an den Skriptblock Foreach-Object zu übergeben.
So erstellen Sie Sicherungskopien einer Datei
Copy-Item ist auch nützlich, um Sicherungskopien für Elemente wie Konfigurationsdateien oder häufig geänderte Dateien in einer Dateifreigabe zu erstellen. In diesem Beispiel wird jede Sicherungskopie in einem datierten Ordner abgelegt, um mehrere Kopien bereitzustellen.
Definieren Sie zunächst die Datumszeichenfolge. Die Häufigkeit der Sicherung bestimmt das Format. Eine tägliche Sicherung hat beispielsweise eine Datumszeichenfolge, die nur das Jahr, den Monat und den Tag oder das Format YYYYMMDD enthält. Dies wird auch als ISO-8601-Format für Datumsangaben bezeichnet und aufgrund seiner relativ einfachen Sortierbarkeit empfohlen.
Für eine einfache tägliche Sicherung generieren Sie die Datumszeichenfolge mit dem folgenden PowerShell-Code:
$dateStr = Get-Date -Format FileDate
Dies gibt eine Zeichenfolge mit dem aktuellen Datum als vierstellige Jahreszahl, zweistelliger Monatsangabe und zweistelliger Tagesangabe zurück.
Definieren Sie als Nächstes die Dateipfade und erstellen Sie bei Bedarf das neue Verzeichnis:
$source = „C:\ProgramData\app\config.json“
$dest = „D:\Backups\app\$dateStr“
if (-not (Test-Path $dest -PathType Container)) {
New-Item -ItemType „directory“ -Path $dest
}
Kopieren Sie abschließend die Datei:
Copy-Item -Path $source -Destination $dest
Um das Backup-Skript optimal zu nutzen, planen Sie es mit dem Taskplaner unter Windows oder als Cron-Job unter Linux.
Verwenden Sie erweiterte PowerShell-Techniken, um Fehler zu überprüfen und eine Kopie fortzusetzen
Das Cmdlet Copy-Item verfügt nicht über Fehlerprüfungs- oder Neustartfunktionen. Für diese Funktionen müssen Sie den Code selbst schreiben.
Das folgende Skript testet den Quelldateipfad, berechnet den Datei-Hash, überprüft die Existenz der Datei und verifiziert die Integrität der kopierten Datei mithilfe eines Hash-Vergleichs. Der Dateikopiervorgang erfolgt innerhalb eines try/catch-Blocks, der für die Ausnahmebehandlung verwendet wird. Wenn ein Fehler auftritt, wird die Meldung Dateikopie fehlgeschlagen (File copy failed) ausgegeben:
function Copy-FileSafer {
[CmdletBinding()]
param (
[string]$path,
[string]$destinationfolder
)
if (-not (Test-Path -Path $path)) {
throw „Datei nicht gefunden: $path“
}
$sourcefile = Split-Path -Path $path -Leaf
$destinationfile = Join-Path -Path $destinationfolder -ChildPath
$sourcefile
$b4hash = Get-FileHash -Path $path
try {
Copy-Item -Path $path -Destination $destinationfolder -ErrorAction
Stop
}
catch {
throw „Dateikopie fehlgeschlagen“
}
finally {
$afhash = Get-FileHash -Path $destinationfile
if ($afhash.Hash -ne $b4hash.Hash) {
throw „Datei während des Kopierens beschädigt“
}
else {
Write-Information -MessageData „Datei erfolgreich kopiert“ -InformationAction Continue
}
}
}
Mit zusätzlichem Code kann das Skript mehrere Versuche rekursiv wiederholen. Nach jedem Kopierversuch kann das Skript den Hash-Wert der Datei berechnen und mit dem Original vergleichen. Stimmen die Werte überein, ist alles in Ordnung. Ist dies nicht der Fall, wird ein Fehler gemeldet.