使用 Get-ChildItem -Exclude 或 -Include returns nothing

Using Get-ChildItem -Exclude or -Include returns nothing

我的 C: 目录中有一个包含很多文件的列表。如果我尝试 运行 对其进行 -Exclude,我不会得到 returns。与 -Include 相同。如果我使用过滤器 returns 我期望得到的结果。我不明白它应该做什么吗?

这是我 运行宁却一无所获的例子:

Get-ChildItem -Path C: -Exclude "*.txt"

我一无所获。如果我运行

Get-Childitem -filter "*.txt"

我回来了:

  Mode                LastWriteTime         Length Name                                                                               
----                -------------         ------ ----                                                                               
-a----        11/7/2007   8:00 AM          17734 eula.1028.txt                                                                      
-a----        11/7/2007   8:00 AM          17734 eula.1031.txt                                                                      
-a----        11/7/2007   8:00 AM          10134 eula.1033.txt                                                                      
-a----        11/7/2007   8:00 AM          17734 eula.1036.txt                                                                      
-a----        11/7/2007   8:00 AM          17734 eula.1040.txt                                                                      
-a----        11/7/2007   8:00 AM            118 eula.1041.txt                                                                      
-a----        11/7/2007   8:00 AM          17734 eula.1042.txt                                                                      
-a----        11/7/2007   8:00 AM          17734 eula.2052.txt                                                                      
-a----        11/7/2007   8:00 AM          17734 eula.3082.txt                                                                      
               7/7/2016   8:50 AM             93 HaxLogs.txt                                                                        
-a----         7/8/2016   8:30 AM              0 Test.txt 
Get-ChildItem -Path "C:\*" -Include "*.txt"

这个关于 -Include 应该如何工作的示例将为您提供您期望的结果。请注意,我还在路径参数中提供了一个通配符,以将路径明确定义为 "any file in the root C:" 而不是 "C:" 本身。

来源: https://technet.microsoft.com/library/hh849800.aspx

此 link 中的示例 3,以防它失效(也请注意此处路径中的通配符):

C:\> Get-ChildItem –Path "C:\Windows\Logs\*" -Include "*.txt" -Exclude "A*"

使用 'C:' 后没有斜杠是您没有得到想要的结果的原因。这被解释为当前目录的相对路径,而不是 C 驱动器的根目录。 (参见:Path with no slash after drive letter and colon - what does it point to?

如果您改用 'C:\',它应该可以正常工作。

编辑:我的错误;我专门针对仅使用“-exclude”的示例做出回应。

总结和补充 and 有用的答案:

您的方法有两个明显的问题:

  • 定位 C: 可能不会(总是)做你想做的事,因为 C: 指的是 无论碰巧是什么当前位置(工作目录)目前在驱动器 C: 上。

    • 要定位驱动器 C: 的 根文件夹 ,您必须使用 C:\,我假设这就是您在本答案其余部分中的意思。
  • 使用 -Exclude(以及 -Include)参数,-Recurse-Path 值都不以 \* 经常没有结果。 出乎意料?确实 - 请参阅下文了解更多信息。

    • 因此,Get-Item -Path C:\* -Exclude *.txt - 请注意从 Get-ChildItemGet-Item 的切换以及 C:\ 之后的 * - 需要使您的命令适用于项目 直接 仅在 C:\ 中。

背景资料:

使用provider-native -Filter参数通常优于-Include,因为:

  • 它比 -Include 快得多,因为提供程序本身在源头执行过滤,而不是让 PowerShell 应用过滤器稍后,所有objects都收到后

  • 不需要您切换到 Get-Item 并将 \* 附加到 -Path 参数值。

      例如,
    • Get-ChildItem -Path C:\ -Filter *.txt 可以很好地匹配 C: 根目录中的所有 *.txt 文件。

也就是说,有注意事项

  • -Filter 支持的通配符模式语言的功能少于 PowerShell 的 - 值得注意的是,它不支持字符 sets/ranges 例如 [0-9] - 可能意外地匹配短 (8.3) 文件名,并且有其他遗留问题 - 请参阅 this well-researched answer 了解详细信息。

  • -Filter 仅支持 单个 模式,而 -Include 支持多个模式(array 个模式)。

不幸的是,-Filter 始终是 positive(包容性)过滤器,因此不能用于提供以下功能-Exclude.


-Include / -ExcludeGet-ChildItem 的实现不直观且有缺陷:

旁注:如果您只使用 one -Include 模式(相对于 -Exclude),将模式直接附加到 -Path 参数更容易;例如:Get-ChildItem C:\*.txt

tl;dr:

要使用 -Include / -Exclude 获得可预测的行为,如果您 不是 也使用 -Recurse(如果您正在使用-Recurse,则此解决方法不需要):

# IMPORTANT: Workaround isn't needed if you're using -Recurse.
#   * "\*" was appended to the input path
#   * Get-*ChildItem* was switched to Get-*Item*
Get-Item C:\path\to\* -Include ...
Get-Item C:\path\to\* -Exclude ...

PowerShell (Core) v7+ 中,if 你的输入路径是 literal,您也可以将 Get-ChildItem-LiteralPath 一起使用,而不是(可能位置隐含)-Path(对当前目录使用 .):

# IMPORTANT: Works in PowerShell (Core) only.
#            Note the use of -LiteralPath.
Get-ChildItem -LiteralPath C:\path\to -Include ...
Get-ChildItem -Literalpath C:\path\to -Exclude ...

  • Windows PowerShell[=290= 中存在 彻底的 bug ] 其中,当使用 -LiteralPath 时,-Include / -Exclude 悄悄忽略 。这已在(至少)v7.0 的 PowerShell (Core) 中修复(并且可以公平地假设它 不会 被修复在 Windows PowerShell 中,它只会收到 关键 修复。

  • -Include-Exclude 并不像直觉上预期的那样工作 ,这是 GitHub issue #3304 的主题:

    • -Include-Exclude 修改 leaf (最后一个)路径组件 -Path 参数,即文件或目录 names 在 file-system 路径的情况下。

    • 这意味着模式首先应用于指定文件夹路径本身的叶组件 应用到 child 项目之前 ,如果有的话。

    • 如果输入路径不以\*结尾且未指定-Recurse,则含义如下:

      • -Include:如果输入路径的最后一个路径组件匹配-Include模式,输入路径本身 被排除(不包括),路径的 child 项目从未被查看 - 没有输出。

      • -Exclude:类似地,如果输入路径的最后一个路径组件确实匹配-Exclude模式,输入路径 本身 被排除,并且路径的 child 项目从未被查看 - 没有任何输出。

        • 目标 root 目录 - 例如,Get-ChildItem -Path C:\ -Exclude Windows) 似乎 完全损坏从 v7.0 开始:它要么根本不产生任何输出,要么在 Unix-like 平台上失败,无论是 -Include 还是 -Exclude,无论使用何种模式 - 请参阅GitHub issue #11649.
      • 如前所述,如果使用 -Recurse 则问题不会出现,因为 强制 下降到输入路径的子树,即使输入路径本身没有被包含/排除。

  • 除非需要-Recurse,否则获得预期行为的唯一方法是替换
    Get-ChildItem C:\path\to -Include / -Exclude
    Get-Item C:\path\to\* -Include / -Exclude - 注意使用 Get-Item 而不是 Get-ChildItem,并且 \*附加到 -Path 参数。

    • 相比之下,如果您将 Get-ChildItem *-Exclude 结合使用,并且 non-excluded 项中有 个目录Get-ChildItem 会意外地输出 它们的内容而不是 ;这 不会 发生在 -Include 并且通常不会发生在子目录匹配 通过通配符表达式 -Path 参数and/or -Filter 参数)。
  • PowerShell 7.2 的问题总结

    • GitHub issue #3304(上面讨论过):-Include / -Exclude 模式的违反直觉的应用仅用于输入本身而不是它们的 children .

    • GitHub issue #11649: Get-ChildItem -Path <rootPath> -Exclude <anyPattern> 意外产生 no 输出(即使 不应排除任何内容,假设排除模式通常应用于输入路径,例如 /c:\)。

    • GitHub issue #9126: -Include / -Exclude 使用 -Recurse 时意外跟随符号链接。

    • GitHub issue #8662:性能问题:-Include / -Exclude 比使用 Where-Object 过滤的 after-the-fact 慢(!)。 =114=]

    • 一个相关的功能请求GitHub issue #15159,它建议引入排除子文件夹子树的能力(而不是只排除与模式本身匹配的项目,而不是他们的 children),使用新参数,例如 -ExcludeSubtree.


示例:-Include / -Exclude

的有问题的使用

注意:要使下面的所有命令都像人们直观预期的那样工作,请将 Get-ChildItem C:\Windows 替换为 Get-Item C:\Windows\* - 请注意使用不同的 cmdlet Get-Item 和附加的 \*.

# HAPPENS TO WORK, BUT IS NOT ROBUST:
# Matches all w* items *inside* C:\Windows, but
# ONLY because w* happens to match 'Windows' - the last input
# path component - too.
Get-ChildItem C:\Windows -Include w*

# HAPPENS TO WORK, BUT IS NOT ROBUST:
# Matches all items whose names *don't* start with a-v *inside* C:\Windows, but
# ONLY because [a-v]* happens not to exclude 'Windows' - the last input
# path component - too.
Get-ChildItem C:\Windows -Exclude [a-v]*


# OUTPUTS NOTHING:
# Because t* doesn't match 'Windows', the child items of 
# 'C:\Windows' are not considered.
Get-ChildItem C:\Windows -Include t*

# OUTPUTS NOTHING:
# Because w* matches 'Windows', it is excluded, and
# the child items of 'C:\Windows' are not considered.     
Get-ChildItem C:\Windows -Exclude w*

这似乎是一个错误(因为父属性的字符串版本是空字符串?)。使用子目录,它工作正常:

get-childitem c:\windows -directory -exclude *.dll

您可以用不同的方式指定根目录,并得到一个奇怪的错误信息:

get-childitem Microsoft.PowerShell.Core\FileSystem::C:\ -exclude *.txt

get-childitem : Cannot process argument because the value of argument "path" is not valid. Change the value of the "path" argument and run the operation again.
At line:1 char:1
+ get-childitem Microsoft.PowerShell.Core\FileSystem::C:\ -exclude wind ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Get-ChildItem], PSArgumentException
    + FullyQualifiedErrorId : Argument,Microsoft.PowerShell.Commands.GetChildItemCommand

或者,在osx中:

get-childitem / -directory -exclude *.txt

get-childitem : Cannot process argument because the value of argument "path" is not valid. Change the value of the "path" argument and run the operation again.
At line:1 char:1
+ get-childitem / -directory -exclude var
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidArgument: (:) [Get-ChildItem], PSArgumentException
+ FullyQualifiedErrorId : Argument,Microsoft.PowerShell.Commands.GetChildItemCommand

这是 powershell 6 及更高版本的解决方法:

get-item c:\ | get-childitem -exclude *.txt