PowerShell,获取具有深度输出的子项

PowerShell,获取具有深度输出的子项,powershell,recursion,Powershell,Recursion,Get ChildItem的-Depth标志让我有点困惑。以下操作非常有效(在“C:\Program files”下只查找一个深度的所有文件和文件夹): 但是,如果我想扩展它以只查找*.txt类型的文件,我就找不到如何做(下面给出了奇怪的意外输出,其中忽略了-Depth 1,它相当于对所有子文件夹进行-Recurse,无论其深度有多深): 我们如何将-Depth用于Get ChildItem和所需文件模式的特定深度?当您使用过滤器而不是包含时,问题得到解决。Filter参数将以正确的模式返回文件

Get ChildItem的
-Depth
标志让我有点困惑。以下操作非常有效(在“C:\Program files”下只查找一个深度的所有文件和文件夹):

但是,如果我想扩展它以只查找*.txt类型的文件,我就找不到如何做(下面给出了奇怪的意外输出,其中忽略了
-Depth 1
,它相当于对所有子文件夹进行
-Recurse
,无论其深度有多深):


我们如何将
-Depth
用于Get ChildItem和所需文件模式的特定深度?

当您使用
过滤器而不是
包含
时,问题得到解决。Filter参数将以正确的模式返回文件,并带有深度。(测试)

进一步澄清Wasif Hasan提出的问题 当我通过官方的Get ChildItem时,它在那里被声明了

使用-Include参数时,如果不包含星号 在路径中,命令不返回任何输出

这意味着
深度
将被自动忽略,因为
包含
所需的行为是递归的。关于-Include的更多细节揭示了这些要点

如果将Recurse参数添加到命令中,则 路径参数中的星号(*)是可选的。递归参数 从路径目录及其子目录获取项。对于 示例,-路径C:\Test \-Recurse-Include*.txt

因此,您要查找的行为位于不需要任何通配符的
Get ChildItem
Filter
标志中

对我来说,
Depth
标志和接受路径中通配符的任何其他标志没有意义,因为
Depth
标志的目的是限制项目中的搜索深度,因为指定通配符不包括该特定目的。 您只需使用此命令即可尝试此操作,例如,如果在路径中指定通配符,您将看到
Depth
参数无效

Get-ChildItem -Path C:\DIRECTORY\* -Depth 1

将返回相同的结果


希望这有助于澄清一些问题

在旧版本的PowerShell中没有深度,在这种情况下,上述内容也可以

Get-ChildItem -Path "C:\DIRECTORY\*","C:\DIRECTORY\*\*"
如果是纯文件名,那么

(Get-ChildItem -Path "c:\program files" -file -Depth 3 -Force -erroraction SilentlyContinue).FullName
与古代的把戏相同,即

(cmd.exe /c dir "c:\program files" /b /a-d /s)|foreach {if ($_.split("\").length -le 5){$_}}

令人惊讶的是,PowerShell甚至比上面这一行还要快!我记得几年前情况并非如此,但我刚刚测试了它,速度快了3-4倍

您看到的行为是Windows PowerShell中的一个错误,该错误已在PowerShell[Core]6+中修复-请参见

鉴于Windows PowerShell不再是主动开发的,因此该漏洞不太可能得到修复

具体来说,Windows PowerShell在以下情况下忽略了
-Depth
的深度约束:

  • 使用
    -包括
    -排除
  • 如果(隐含的)
    -Path
    参数包含通配符
当仍然执行递归时,不施加深度限制;实际上,
-Depth
在这些情况下的行为类似于
-Recurse
(单独)

变通办法

  • 对于
    -包括
    和基于通配符的
    -路径
    参数,其中通配符仅限于最后一个路径组件:

    • 改用
      -Filter
      ,如中所示
    • 注意事项
      -过滤器
      通常因其卓越的性能而更受欢迎,但其通配符语言不如PowerShell强大,并且有一些遗留问题-值得注意的是,字符集和范围(
      […]
      )不支持,例如,在Windows PowerShell中,诸如
      *.xls
      之类的筛选器也与
      *.xlsx
      文件匹配-请参阅
  • 对于
    -排除

    • 仅使用
      -Depth
      ,通过调用在事实发生后执行过滤;e、 g.,
      Get ChildItem-File'C:\Program Files\'-Depth 1 | Where Object Name-NotLike*.txt
  • [可能很少需要]对于基于通配符的
    -Path
    参数,在除最后一个(例如,
    C:\foo*\bar
    )以外的组件中使用通配符

    • 使用
      -Recurse
      并使用
      Where Object
      在事实之后执行过滤;在这种情况下,还必须通过计算路径组件的数量来剔除太深的路径

是的,谢谢,我还想说这没有道理。给我一个错误,或一个有意义的警告,指出我的语法可能是错误的,不要给我奇怪的意外结果。我看不出有什么理由不能编写
Depth
,从而使它在其他情况下按预期运行。一切似乎都有点适得其反。我想知道这个Cmdlet的作者对这个奇怪的输出结果是怎么想的。这个行为是Windows PowerShell中的一个bug,它已经在PowerShell[Core]6+中修复了-请参阅。是的,
-Filter
不要求
-Path
参数以
*
结尾才能生效,但是如果还执行递归,
-Include
也不要求生效,并且使用
-Depth
意味着
-Recurse
。正是这个bug使两个深度不同的
C:\DIRECTORY\*
命令输出相同的结果,
-Depth
限制再次被忽略。@mklement0同意报告的问题,但不确定为什么
-Include
的官方文档声明它需要在路径中使用通配符或将返回empty@DevX,这是由于一个不相关的问题,即不幸的事实是,如果没有递归,
-Include
模式(首先)与输入路径本身匹配,这意味着通常没有匹配。将
\*
附加到输入路径中会产生
Get-ChildItem -Path C:\DIRECTORY\* -Depth 2
Get-ChildItem -Path "C:\DIRECTORY\*","C:\DIRECTORY\*\*"
(Get-ChildItem -Path "c:\program files" -file -Depth 3 -Force -erroraction SilentlyContinue).FullName
(cmd.exe /c dir "c:\program files" /b /a-d /s)|foreach {if ($_.split("\").length -le 5){$_}}