请注意,语法规范要求一个字符串数组,即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元素数组。
如果您在家中尝试此操作,请确保使用Replace-Variable“省略”清除$omissions的存在,然后再进行上述示例中的转换。
至于我测试过并且可靠工作的管道...
--------------------------------------------------------------------------------------- cd $sourcelocation
ls | ?{$_ -ne $null} | ?{$_.BaseName -notmatch "^\.$"} | %{$_.Name} | cp -Destination $targetDir -Exclude $omissions -recurse -ErrorAction silentlycontinue
---------------------------------------------------------------------------------------
上面的代码列出了当前目录中源文件的目录列表,过滤掉潜在的问题项,将文件转换为基本名称,并强制cp(copy-item alias)通过“名称”在“当前目录”中重新访问文件 - 从而重新获取文件对象并复制它。这将创建空目录,包括可能包含被排除文件的目录(当然不包括这些被排除的文件)。还要注意,“ls”(get-childitem)不会递归 - 这留给了cp。最后 - 如果您遇到问题并需要调试,请删除-ErrorAction silentlycontinue开关和参数,否则会隐藏许多可能中断脚本的烦恼。
对于那些与“\”包含相关的评论,请记住,您是通过解释器(即PowerShell)在.NET子层上工作的,在c#中,例如,包含单个“\”(或多个字符串中的单个“\”)导致编译器要求您通过使用“\\”来转义反斜杠,或者在字符串前面加上@,如@“\”; 剩下的选项是将字符串封装在单引号中,如'\'。所有这些都是由于ASCII插值造成的字符组合,如“\n”等。
后面的主题更大,所以我就把它留给你去考虑吧。