Обратите внимание, что в спецификации синтаксиса требуется STRING ARRAY; 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>]
Если вы не явно указали в генерации своего массива, вы получите Object [] - и это во многих случаях игнорируется, оставляя видимость «глючного поведения» из-за безопасности типов. Поскольку PowerShell может обрабатывать блоки сценариев, оценка переменной, не зависящей от типа (чтобы можно было определить допустимую строку), оставила бы возможность для атаки в режиме внедрения на любую систему, политика выполнения которой была слабой.
Так что это ненадежно:
PS > $omissions = @("*.iso","*.pdf","*.zip","*.msi")
PS > $omissions.GetType()
Note the result....
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
И это работает .... например:
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
Обратите внимание, что даже для "одного" элемента все равно потребуется такое же приведение, чтобы создать массив из 1 элемента.
Если вы пытаетесь сделать это дома, обязательно используйте «пропуски» Переменной-переменной, чтобы очистить существование $ упущений, прежде чем переписать его в приведенных выше примерах.
А что касается проверенного надежного конвейера, который я тестировал ...
--------------------------------------------------------------------------------------- cd $sourcelocation
ls | ?{$_ -ne $null} | ?{$_.BaseName -notmatch "^\.$"} | %{$_.Name} | cp -Destination $targetDir -Exclude $omissions -recurse -ErrorAction silentlycontinue
---------------------------------------------------------------------------------------
Выше приведен список каталогов исходных файлов в базовом (выбранном «текущем») каталоге, отфильтровывает потенциальные проблемные элементы, преобразует файл в базовое имя и вынуждает cp (псевдоним элемента копирования) повторно обращаться к файл «по имени» в «текущем каталоге» - таким образом, повторно запрашивает объект файла и копирует его. Это создаст пустые каталоги, в том числе те, которые могут даже содержать исключенные файлы (за исключением, конечно, исключений). Также обратите внимание, что "ls" (get-childitem) не -recurse - это оставлено для cp. Наконец, если у вас возникли проблемы и вам необходимо выполнить отладку, удалите ключ-аргумент -ErrorAction без вывода сообщений, который скрывает множество неприятностей, которые в противном случае могут прервать выполнение сценария.
Для тех, чьи комментарии были связаны с "\" включениями, имейте в виду, что вы работаете над подуровнем .NET через интерпретатор (например, PowerShell), а в c #, например, включение одного " \ "(или несколько одиночных строк в строке) приводит к тому, что компилятор требует, чтобы вы исправили условие, используя либо" \\ "для экранирования обратной косой черты, либо перед строкой @, как в @" \ "; с другим оставшимся параметром, заключающим строку в одинарные кавычки, как '\'. Все это из-за ASCII-интерполяции комбинаций символов, таких как \ n и т. Д.
Последний вопрос гораздо важнее, поэтому я оставлю вас с этим соображением.