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

标签 powershell get-childitem

好的,所以我觉得这一定是 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 switch 导致 cmdlet 返回错误,而不是上面显示的(误导性的)空响应。我用 -Include * 测试了相同的命令选项,仍然没有结果,但是这次结合-Recurse没有错误转变。

-文字路径

最适合我的是用 -LiteralPath 指定路径范围:
[PS]> gci -LiteralPath '.\Music\Artist - Name\Album Name [Disc 1]\'

逃跑

为了涵盖其他一些可能的情况,您可能想要尝试对方括号进行转义。使用来自@PetSerAl 在 OP 评论中的建议,您可以尝试以下操作:
[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``]\'

有关方括号和转义的更多信息,请参阅以下问答:
  • 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/

    相关文章:

    powershell - 获取异常 “System.TypeInitializationException,WebSphereMQ.<Command Name>”-mo74_PowerShell

    powershell - 替换/重命名对象属性名称

    powershell - 使用动态构造的排除模式数组,使用 Get-ChildItem -Exclude 过滤子文件夹

    powershell - 获取最接近给定日期的文件

    powershell - Get-ChildItem和不间断空格

    powershell - PowerShell的v2.0和v3.0文件夹在哪里?

    arrays - 当我在 PowerShell 中更改数组的值时,我不断收到 "Unable to index into an object of type System.String."

    windows - 如何在 PowerShell 中使用 cmd 类型的管道 (/piping)?

    powershell - 能做到吗根据文件使用Powershell的年代删除大量文件

    powershell - 当一个列表可能只是 Get-Item 中的一项时,如何在 PowerShell 中合并两个 "lists"?