Powershell Get Childitem Exclude 在当前目录中不起作用

Powershell Get Child Item Exclude doesn't work in current directory

正如我在问题中提到的,这似乎是 Powershell 引擎中的错误。

当我尝试通过排除某些文件类型(扩展名)来打印当前目录(也存在上述 powershell 脚本)中的文件时,它没有打印任何内容。例如。下面的代码在 Powershell 控制台中打印当前文件夹的内容:

gci
gci -pa .

以上代码打印目录内容如下:

Mode                LastWriteTime         Length Name                                                                                     
----                -------------         ------ ----                                                                                     
-a----       20-09-2020     22:37      835799796 file1.mkv                                                                      
-a----       20-09-2020     22:25            148 file1.srt                                      
-a----       23-09-2020     04:53            357 scriptv1.ps1                                                           
-a----       20-09-2020     22:25            678 file1.txt

但是当我 运行 下面的代码时,它不打印任何东西,当它必须打印 file1.txt:

$excluded = @('*.mkv','*.mp4','*.srt','*.sub','*.ps1')
Get-ChildItem -Exclude $excluded | Write-Host { $_.FullName }

任何人都可以帮助弄清楚为什么会发生这种情况以及如何得到我提到的内容吗?

您在 gci 示例中正确地执行了排除参数,但它可能在您的控制台中静默地处理结果到 write-host 的地方,因为它不处理 { .. } 脚本块作为 foreach-object 将对单个项目执行。静默错误应该是:

Write-Host: The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.

在这方面,正确的短 foreach-object 管道表示法是:

$excluded = @('*.mkv','*.mp4','*.srt','*.sub','*.ps1')
Get-ChildItem -Exclude $excluded | % { Write-Host $_.FullName }

关于静默错误,我假设您的会话设置为 Silent,您可以使用 $ErrorActionPreference 变量进行检查。如果您希望看到所有错误 - 在 non-blocking 模式下,您可以将其设置为 Continue 例如:

$ErrorActionPreference='Continue'

相关 PS7 页面和示例:

Get-ChildItem -Exclude $excluded | Write-Host { $_.FullName } 除非您目录中的所有子项都被您的过滤器排除,否则不应静默失败。

如果您尝试在非空目录中 运行 Get-ChildItem | Write-Host { $_.FullName },它应该会抛出类似于此的错误:

Write-Host: The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.

原因是Write-Host不能将数组作为参数(通过(Get-ChildItem).GetType()我们知道这是一个数组)。

因此,您需要首先使用 ForEach-Object 或其别名之一迭代数组的元素:foreach%.

$excluded = @('*.mkv','*.mp4','*.srt','*.sub','*.ps1')
Get-ChildItem -Exclude $excluded | ForEach-Object { Write-Host $_.FullName }
Get-ChildItem -Exclude $excluded | foreach { Write-Host $_.FullName }
Get-ChildItem -Exclude $excluded | % { Write-Host $_.FullName }

-ExcludeGet-ChildItem 一起使用并不直观。要使用 Get-ChildItem 获得一致的结果,您必须使用 \* 限定您的路径或使用 -Recurse 开关。如果你不关心递归,你可以只使用 Get-Item\* 限定路径。

# Works but includes all subdirectory searches
Get-ChildItem -Path .\* -Exclude $excluded
Get-ChildItem -Path .\* -Exclude $excluded -File
Get-ChildItem -Path . -Exclude $excluded -File -Recurse

# Best results for one directory
Get-Item -Path .\* -Exclude $excluded

应该使用递归的原因是因为 -Exclude 值首先应用于 -Path 值的叶子。如果这些排除中的任何一个与您的目标目录相匹配,那么它将被排除并阻止显示其任何项目。见下文:

$path = 'c:\temp'
# produces nothing because t* matches temp
Get-ChildItem -Path $path -Exclude 't*'