Beachten Sie, dass die Syntaxspezifikation einen STRING ARRAY erfordert. ala String []
SYNTAX
Copy-Item [[-Destination] <String>] [-Confirm] [-Container] [-Credential <PSCredential>] [-Exclude <String[]>] [-Filter <String>] [-Force] [-FromSession <PSSession>] [-Include
<String[]>] -LiteralPath <String[]> [-PassThru] [-Recurse] [-ToSession <PSSession>] [-UseTransaction] [-WhatIf] [<CommonParameters>]
Wenn Sie in Ihrer Array-Generierung nicht explizit sind, erhalten Sie ein Objekt [] - und das wird in vielen Fällen ignoriert, sodass aufgrund der Typensicherheit das Erscheinungsbild eines "fehlerhaften Verhaltens" auftritt. Da PowerShell Skriptblöcke verarbeiten kann, würde die Auswertung einer anderen als einer typspezifischen Variablen (damit eine gültige Zeichenfolge ermittelt werden kann) eine Öffnung für das Potenzial eines Angriffs im Injektionsmodus auf jedes System hinterlassen, dessen Ausführungsrichtlinie lax war.
Das ist also unzuverlässig:
PS > $omissions = @("*.iso","*.pdf","*.zip","*.msi")
PS > $omissions.GetType()
Note the result....
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
Und das funktioniert ... zum Beispiel:
PS > $omissions = [string[]]@("*.iso","*.pdf","*.zip","*.msi")
**or**
PS > [string[]]$omissions = ("*.iso,*.pdf,*.zip,*.msi").split(',')
PS > $omissions.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String[] System.Array
Beachten Sie, dass selbst ein "einzelnes" Element immer noch dieselbe Umwandlung erfordert, um ein Array mit 1 Element zu erstellen.
Wenn Sie dies zu Hause versuchen, stellen Sie sicher, dass Sie die "Auslassungen" der Ersetzungsvariablen verwenden, um das Vorhandensein von $ Auslassungen zu beseitigen, bevor Sie sie in den oben gezeigten Beispielen neu zusammenstellen.
Und was eine Pipeline betrifft, die zuverlässig funktioniert, die ich getestet habe ...
--------------------------------------------------------------------------------------- cd $sourcelocation
ls | ?{$_ -ne $null} | ?{$_.BaseName -notmatch "^\.$"} | %{$_.Name} | cp -Destination $targetDir -Exclude $omissions -recurse -ErrorAction silentlycontinue
---------------------------------------------------------------------------------------
Oben wird eine Verzeichnisliste der Quelldateien im Basisverzeichnis (ausgewählt "aktuell") erstellt, potenzielle Problemelemente herausgefiltert, die Datei in den Basisnamen konvertiert und cp (Alias für Kopierelemente) gezwungen, erneut auf die Datei zuzugreifen name "im" aktuellen Verzeichnis "- so wird das Dateiobjekt erneut abgerufen und kopiert. Dadurch werden leere Verzeichnisse erstellt, einschließlich solcher, die möglicherweise sogar ausgeschlossene Dateien enthalten (natürlich abzüglich der Ausschlüsse). Beachten Sie auch, dass "ls" (get-childitem) NICHT -recurse ist - das bleibt cp überlassen. Schließlich - wenn Sie Probleme haben und debuggen müssen, entfernen Sie den Schalter -ErrorAction Silentcontinue und das Argument, das viele Belästigungen verbirgt, die das Skript andernfalls unterbrechen könnten.
Beachten Sie für diejenigen, deren Kommentare sich auf "\" -Einschlüsse beziehen, dass Sie über die .NET-Unterschicht über einen Interpreter (z. B. PowerShell) arbeiten und in c # beispielsweise ein einzelnes "\" ( oder mehrere Singles in einer Zeichenfolge), führt der Compiler dazu, dass Sie die Bedingung korrigieren müssen, indem Sie entweder "\\" verwenden, um dem Backslash zu entkommen, oder der Zeichenfolge ein @ wie in @ "\" voranstellen. Die andere verbleibende Option ist das Einschließen der Zeichenfolge in einfache Anführungszeichen als '\'. All dies ist auf die ASCII-Interpolation von Zeichenkombinationen wie "\ n" usw. zurückzuführen.
Letzteres ist ein viel größeres Thema, daher überlasse ich Ihnen diese Überlegung.