使用 PowerShell 从文件夹中获取文件名的 fastest\best 方法是什么?

What is the fastest\best way to get file names from a folder using PowerShell?

该目录有20k个文件夹。在这些文件夹中有子文件夹和一些文件。我不需要查看子文件夹。我需要从文件夹中获取所有扩展名为 .EIA 的文件。

我知道我可以为此使用 Get-Item、Get-ChildItem,但这些 cmdlet 获取数据的速度太慢。此外,此脚本必须每小时 运行,因此,它不能占用超长的时间。

我正在尝试使用 [System.IO.File]::GetFiles($path),但这会出错

 Method invocation failed because [System.IO.File] does not contain a method named 'GetFile'

我也试过了

$pathEia = "\Sidney2\MfgLib\AidLibTest\*\*.EIA"
 [System.IO.File]::GetFiles($pathEia)

这也会引发错误:

 Exception calling "GetFiles" with "1" argument(s): "The filename, directory name, or volume label
     | syntax is incorrect. : '\Sidney2\MfgLib\AidLibTest\*\*.EIA'"

我正在使用 PowerShell 核心 7.2 .Net Framework 4.8 任何帮助表示赞赏。提前致谢。

尝试以下操作:

$path = '\Sidney2\MfgLib\AidLibTest'
$allFilePathsOfInterest =
  foreach ($dir in [System.IO.Directory]::GetDirectories($path)) {
    [System.IO.Directory]::GetFiles($dir, '*.EIA')
  }

鉴于输入目录路径是 完整 路径,$allFilesOfInterest 也是完整文件路径的数组。

如果您只需要文件 names,请使用要返回的 [System.IO.DirectoryInfo] type instead of the static methods of the [System.IO.Directory] type, which allows you to access the .Name property of the [System.IO.FileInfo] 个实例的 instance 方法:

$path = '\Sidney2\MfgLib\AidLibTest'
$allFileNamesOfInterest =
  foreach ($dir in [System.IO.DirectoryInfo]::new($path).GetDirectories()) {
    $dir.GetFiles('*.EIA').Name
  }
  • 请注意 two-step 方法 - 首先获取子目录,然后检查它们的文件 - 因为我不知道允许您处理的标准 .NET API跨层级的通配符(例如,\Sidney2\MfgLib\AidLibTest\*\*.EIA')。

  • 如果您需要更多地控制文件和目录的枚举,GetDirectories and GetFiles methods offer overloads that accept a System.IO.EnumerationOptions 实例,但不幸的是,仅在 PowerShell (Core) 7+ / .NET (Core) 中:

    • Windows PowerShell / .NET Framework 仅提供 System.IO.SearchOption 实例的重载,但唯一控制的是枚举是否 递归

非常类似于 but using the instance methods from DirectoryInfo

EnumerationOptions is available starting from .NET Core 2.1. This class has the property IgnoreInaccessible 默认设置为 $true 在以前的版本中,异常会导致枚举停止 :

...skip files or directories when access is denied (for example, UnauthorizedAccessException or SecurityException).

此答案需要 PowerShell Core 7+

# Skip the following Attributes:
#   2.    Hidden
#   4.    System
#   1024. ReparsePoint
#   512.  SparseFile

$enum = [IO.EnumerationOptions]@{
    RecurseSubdirectories = $false # Set to `$true` if you need to do a recursive search
    AttributesToSkip      = 2, 4, 1024, 512
}

$start  = [IO.DirectoryInfo]::new('\Sidney2\MfgLib\AidLibTest')
$result = foreach($dir in $start.EnumerateDirectories()) {
    $dir.GetFiles('*.EIA', $using:enum)
}
$result | Format-Table

如果需要对子文件夹进行递归搜索(如果RecurseSubdirectories = $true),可以考虑使用multi-threadingForEach-Object -Parallel .

$start  = [IO.DirectoryInfo]::new('\Sidney2\MfgLib\AidLibTest')
$result = $start.EnumerateDirectories() | ForEach-Object -Parallel {
    $_.GetFiles('*.EIA', $using:enum)
}
$result | Format-Table

重要的是要注意,使用并行循环 可能会也可能不会比有效的线性循环(例如foreach), as :

Parallelism works best for different disks/shares/computers.