当输入路径中有方括号时,Get-ChildItem -Recurse是否被破坏?

时间:2015-11-15 16:16:55

标签: powershell get-childitem

好的,所以我觉得这个必须是PowerShell中的一个错误,但我想知道你们是否认为这听起来很糟糕。复制它很容易,但我可以看出为什么它可能不是一个特别常见的用例。我在下面列出的步骤实际上并不是我的脚本所做的事情,我实际上是在计算子文件夹的大小 - 我只是简单地将其压缩到显示我的问题的最简单的场景。

我在PowerShell 5.0.10240.16384上只尝试了这个,但可能很快就有机会在早期版本上测试它[编辑:我现在在PowerShell 2.0上测试了这个,而且bug确实存在出现在该版本中 - 它按预期工作]。只是一个简单的说明 - 我使用gci作为Get-ChildItem的缩写。如果您还不知道,那么实际上也可以输入PowerShell。但问题在于你使用的别名。

首先,在某个地方创建一个名为Test [123]的文件夹。在该文件夹中,创建几个文件。我的名为Test1.txtTest2.txt。他们不需要任何东西。

接下来,打开PowerShell会话并Set-Location到新Test [123]文件夹的父文件夹

现在,运行gci -Filter Test*,您应该看到类似的内容:

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       11/15/2015   3:22 PM                Test [123]

一切都好,对吗?接下来,尝试gci -Filter Test* | gci。这使得第一个gci的输出成为下一个gci的输入,即向我们显示第一个gci返回的每个项目的子项。这给了我们以下内容:

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       11/14/2015  10:21 PM              0 Test1.txt
-a----       11/15/2015   3:55 PM              0 Test2.txt

再一次,一切都很好 - 完全符合预期。这是我们Test [123]文件夹中的所有文件。

现在试试这个:gci -Filter Test* | gci -Recurse。我们所有改变的是,对gci的第二次调用现在是递归的,因此它应该向我们显示包括子文件夹在内的所有文件。我们没有任何子文件夹,所以我们期待相同的结果,对吗?

错误。我们根本得不到任何输出。似乎非常奇怪,我们所做的就是添加-Recurse,现在我们得到了不同的输出。我认为添加-Recurse永远不应该渲染较少的输出,只会更多。

这是下一个奇怪的事情。现在尝试gci -Filter Test* | gci -Recurse -Name。除了添加了-Name参数之外,这与之前相同。这只是说我们想要相同的输出,除了我们只想要文件名而不是每个项目的完整信息。所以我们可能不期待什么。但那不是我们得到的,我们得到了这个:

Test1.txt
Test2.txt

这已经得到被打破了,对吗?首先-Recurse永远不应该减少输出量,其次要求不同格式的输出不应该改变我们得到的输出量。

仅当文件夹名称中有方括号时才会发生这种情况。如果您创建了另一个名为Test的文件夹,并再次运行上述所有命令,您将始终看到Test文件夹中的文件。

我的研究引导我进入-LiteralPath参数;但是,将上述命令改为gci -Filter Test* | foreach { gci -Recurse -LiteralPath $_ },以便使用该参数仍然不返回任何输出,并再次添加-Name参数将启动再次返回的文件。

我设法为此做了一个变通方法,使用-Name参数,然后将其与我搜索的文件夹的路径相结合,然后将其传递到Get-Item但是,这使代码变得更长,更难以实现。

所以我的问题是,我犯了错误或误解了什么吗?或者这是我应该报告的错误吗?

2 个答案:

答案 0 :(得分:5)

看起来像是here报告的错误或非常类似的问题。

答案 1 :(得分:0)

TL; DR:如果名称中可能包含不寻常的字符(包括方括号),请使用-LiteralPath作为文件夹。


根据PowerShell v5.1.17134.590中的OP,我无法重现此内容。

但是,我能够复制类似的内容,使用以下命令尝试列出我怀疑为空的文件夹中的文件,以便删除该文件。实际上,此文件夹中有12个.mp3文件:

[PS]> gci '.\Music\Artist - Name\Album Name [Disc 1]\'

[PS]>

添加-Recurse开关导致cmdlet返回错误,而不是上面显示的(误导)空响应。我使用-Include *选项测试了同一命令,但仍然没有结果,但是这次与-Recurse开关组合使用时没有错误。

-LiteralPath

最适合我的是使用-LiteralPath参数指定路径:

[PS]> gci -LiteralPath '.\Music\Artist - Name\Album Name [Disc 1]\'

转义

要涵盖其他一些可能的情况,您可能想尝试转义方括号。在OP的评论中使用@PetSerAl的建议,您可以尝试执行以下操作:

[PS]> [System.Management.Automation.WildcardPattern]::Escape('.\Music\Artist - Name\Album Name [Disc 1]\')

.\Music\Artist - Name\Album Name `[Disc 1`]\

可悲的是,这并没有立即起作用。我发现我需要转义两次,然后以下命令给出了正确的目录清单:

[PS]> gci '.\Music\Artist - Name\Album Name ``[Disc 1``]\'

有关方括号和转义的更多信息,请参见以下问答: