使用 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-threading和ForEach-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.
该目录有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
andGetFiles
methods offer overloads that accept aSystem.IO.EnumerationOptions
实例,但不幸的是,仅在 PowerShell (Core) 7+ / .NET (Core) 中:- Windows PowerShell / .NET Framework 仅提供
System.IO.SearchOption
实例的重载,但唯一控制的是枚举是否 递归 。
- Windows PowerShell / .NET Framework 仅提供
非常类似于 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-threading和ForEach-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.