我有这个代码,我非常满意:
$jpgExtensionFiles = New-Object System.Collections.ArrayList
$AllDrives = Get-PSDrive
foreach ($Drive in $AllDrives) {
$Dirs = Get-ChildItem $Drive.Root -Recurse -ErrorAction SilentlyContinue
$jpgExtensionFiles.Add(($Dirs | where {$_.extension -eq ".jpg"}))
}
但是现在,我想对一个名为$bmpExtensionFiles
的数组做同样的事情。我无法弄清楚如何执行以下操作:
...所有在一个循环中。我知道我可以添加$bmpExtensionFiles.Add(($Dirs | where {$_.extension -eq ".bmp"}))
,但是有更有效的方法吗?我需要兼容PowerShell v2。
答案 0 :(得分:2)
您可以使用switch语句,如果您想稍后添加其他类型,则可以轻松扩展:
ForEach ($Dir in $Dirs)
{
Switch ($Dir.Extension)
{
".jpg" {$jpgExtensionFiles.Add($Dir)}
".bmp" {$bmpExtensionFiles.Add($Dir)}
}
}
答案 1 :(得分:1)
未经过广泛测试,但应该非常有效。
$jpgExtensionFiles,$bmpExtensionfiles = (Get-ChildItem $Drive.Root -Recurse -include *.jpg,*.bmp -ErrorAction SilentlyContinue).where({$_.extension -eq '.jpg'},'split')
答案 2 :(得分:0)
以下基于散列表的解决方案 概括为任意数量的扩展程序:
使用Get-ChildItem -Filter
# Initialize a hashtable for all extexnsions of interest:
# Key is the extension name, value is an array list to be filled
# with the files ([System.IO.FileInfo] instances) having that extension.
$htFilesByType = @{
'.jpg' = New-Object System.Collections.ArrayList
'.bmp' = New-Object System.Collections.ArrayList
}
# Get the list of all filesystem PS drives.
$AllFsDrives = Get-PSDrive -PSProvider FileSystem
# Loop over all filesystem drives.
foreach ($Drive in $AllFsDrives) {
# Loop over all extensions and add files with that extension to the hashtable.
foreach ($ext in $htFilesByType.Keys) {
# Get all files with the extension at hand at once and add them
# to the relevant hashtable entry.
# Note: The .Add() method returns a value, which we're not interested in,
# hence the `$null = ...`.
$null = $htFilesByType[$ext].Add(
(Get-ChildItem -Filter "*$ext" $Drive.Root -Recurse -ErrorAction SilentlyContinue)
)
}
}
# Output the filled hashtable.
$htFilesByType
注意:乍一看,为每个扩展程序运行Get-ChildItem -Recurse -Filter <ext>
似乎效率低下,但对于小扩展程序,这可能仍然比单个扩展程序更快通过以下Get-ChildItem -Recurse -Include <ext1>, <ext2>, ...
解决方案:
-Filter
参数是drive-provider-native并在 source 处过滤,这使得它比-Include
参数更有效。
不幸的是,-Filter
仅支持单过滤器(通配符表达式,例如*.jpg
),这就是需要多次传递的原因。
另请注意,为简单起见,将在每次传递中首先收集整个匹配文件数组,然后将其作为整体添加到哈希表中。这很快,但也耗费内存;如果这是一个问题,请逐个处理文件,如下面的单程解决方案。
难以预测单遍解决方案变得更快的确切点,因为涉及的因素很多(匹配文件与不匹配文件的比率,通过次数) ,...)
如有疑问,请使用Measure-Command
来比较这两种解决方案。
Get-ChildItem -Include
命令# Construct the array of wildcard expressions to use with -Include;
# e.g., @( '*.jpg', '*.bmp' )
$includes = $htFilesByType.keys -replace '^', '*'
foreach ($Drive in $AllFsDrives) {
# Look for files with any of the extensions of interest.
Get-ChildItem -Include $includes $Drive.Root -Recurse -ErrorAction SilentlyContinue |
ForEach-Object {
# Add to the appropriate array list based on the matching file's extension.
$null = $htFilesByType[$_.Extension].Add($_)
}
}
注意:在PSv3或更高版本中,您可以通过添加Get-ChildItem
开关来限制与文件的匹配,从而略微提高-File
命令的效率。