检查文件扩展名是否以此OR结束的最有效方法是什么?

时间:2017-01-17 14:08:18

标签: arrays file powershell powershell-v2.0 get-childitem

我有这个代码,我非常满意:

$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的数组做同样的事情。我无法弄清楚如何执行以下操作:

  1. 如果扩展名为.jpg,请添加到第一个数组
  2. 如果扩展名为.bmp,请添加到第二个数组
  3. 为了效率,

    ...所有在一个循环中。我知道我可以添加$bmpExtensionFiles.Add(($Dirs | where {$_.extension -eq ".bmp"})),但是有更有效的方法吗?我需要兼容PowerShell v2。

3 个答案:

答案 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

-pass解决方案
# 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命令

单个 -pass解决方案:

# 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命令的效率。