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

我仅在PowerShell 5.0.10240.16384上尝试过此操作,但可能很快就有机会在较早版本上进行了测试[编辑:我现在已经在PowerShell 2.0上进行了此测试,该错误确实是而不是出现在该版本中-它按预期工作]。简要说明-我在整个过程中都使用gci作为Get-ChildItem的缩写。如果您还不知道,那么实际上也可以键入PowerShell。但是,无论使用哪种别名,问题都存在。

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

接下来,打开一个PowerShell session 并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,但这使代码变得比所需的更长和难看。

所以我的问题是,我是否犯了错误或误解了?还是这是我应该报告的错误?

最佳答案

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参数指定路径:
[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`]\

可悲的是,这并没有立即生效。我发现我需要转义两次,然后以下命令给出了正确的目录 list :
[PS]> gci '.\Music\Artist - Name\Album Name ``[Disc 1``]\'

有关方括号和转义的更多信息,请参见以下问答:
  • How do I use square brackets in a wildcard pattern in PowerShell Get-ChildItem?
  • 关于powershell - 输入路径中有方括号时,Get-ChildItem -Recurse是否损坏?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33721892/

    10-13 07:51