Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 提高我的PowerShell脚本的效率_Performance_Powershell_Coding Efficiency - Fatal编程技术网

Performance 提高我的PowerShell脚本的效率

Performance 提高我的PowerShell脚本的效率,performance,powershell,coding-efficiency,Performance,Powershell,Coding Efficiency,下面的代码从list.txt文件中搜索400多个数字,以查看它是否存在于指定文件夹路径内的任何文件中 脚本速度非常慢,尚未完成,因为它在运行25分钟后未完成。我们正在搜索的文件夹为507MB(532369408字节),其中包含1119个文件,480个文件夹。我们非常感谢任何有助于提高搜索速度和效率的帮助 $searchWords = (gc 'C:\temp\list.txt') -split ',' $results = @() Foreach ($sw in $searchWords) {

下面的代码从list.txt文件中搜索400多个数字,以查看它是否存在于指定文件夹路径内的任何文件中

脚本速度非常慢,尚未完成,因为它在运行25分钟后未完成。我们正在搜索的文件夹为507MB(532369408字节),其中包含1119个文件480个文件夹。我们非常感谢任何有助于提高搜索速度和效率的帮助

$searchWords = (gc 'C:\temp\list.txt') -split ','
$results = @()
Foreach ($sw in $searchWords)
{
    $files = gci -path 'C:\Users\david.craven\Dropbox\Asset Tagging\_SJC Warehouse_\_Project Completed_\2018\A*' -filter "*$sw*" -recurse

    foreach ($file in $files)
    {
        $object = New-Object System.Object
        $object | Add-Member -Type NoteProperty –Name SearchWord –Value $sw
        $object | Add-Member -Type NoteProperty –Name FoundFile –Value $file.FullName
        $results += $object
    }

}

$results | Export-Csv C:\temp\output.csv -NoTypeInformation

以下几点可以大大加快您的任务速度:

如果目的确实是在文件名中查找搜索词:

$searchWords = (Get-Content 'C:\temp\list.txt') -split ','
$path = 'C:\Users\david.craven\Dropbox\Facebook Asset Tagging\_SJC Warehouse_\_Project Completed_\2018\A*'

Get-ChildItem -File -Path $path -Recurse -PipelineVariable file |
  Select-Object -ExpandProperty Name |
    Select-String -List -SimpleMatch -Pattern $searchWords |
      Select-Object @{n='SearchWord'; e={$_.Pattern}},
                    @{n='FoundFile'; e={$file.FullName}} |
        Export-Csv C:\temp\output.csv -NoTypeInformation
$searchWords = (Get-Content 'C:\temp\list.txt') -split ','
$path = 'C:\Users\david.craven\Dropbox\Facebook Asset Tagging\_SJC Warehouse_\_Project Completed_\2018\A*'

Get-ChildItem -File -Path $path -Recurse |
  Select-String -SimpleMatch -Pattern $searchWords |
    Select-Object @{n='SearchWord'; e={$_.Pattern}},
                  @{n='FoundFile'; e={$_.Path}} |
      Export-Csv C:\temp\output.csv -NoTypeInformation

如果目的是在文件内容中查找搜索词:

$searchWords = (Get-Content 'C:\temp\list.txt') -split ','
$path = 'C:\Users\david.craven\Dropbox\Facebook Asset Tagging\_SJC Warehouse_\_Project Completed_\2018\A*'

Get-ChildItem -File -Path $path -Recurse -PipelineVariable file |
  Select-Object -ExpandProperty Name |
    Select-String -List -SimpleMatch -Pattern $searchWords |
      Select-Object @{n='SearchWord'; e={$_.Pattern}},
                    @{n='FoundFile'; e={$file.FullName}} |
        Export-Csv C:\temp\output.csv -NoTypeInformation
$searchWords = (Get-Content 'C:\temp\list.txt') -split ','
$path = 'C:\Users\david.craven\Dropbox\Facebook Asset Tagging\_SJC Warehouse_\_Project Completed_\2018\A*'

Get-ChildItem -File -Path $path -Recurse |
  Select-String -SimpleMatch -Pattern $searchWords |
    Select-Object @{n='SearchWord'; e={$_.Pattern}},
                  @{n='FoundFile'; e={$_.Path}} |
      Export-Csv C:\temp\output.csv -NoTypeInformation

提高绩效的关键:

  • 通过将所有搜索词传递给
    Select String
    ,使用单个命令执行搜索

  • 与其在脚本块中使用
    新对象
    添加成员
    构造自定义对象,不如让
    选择对象
    直接在管道中使用来构造对象

  • 与使用
    +=
    迭代构建中间数组(每次都在幕后重新创建数组)不同,使用单个管道将结果对象直接传输到
    导出Csv


因此,您发布的PowerShell代码中肯定有一些基本的东西可以改进,但可能仍然不是很快。根据您给我们的示例,我假设您希望将文件名与单词列表进行匹配。在单词列表中循环(400次迭代),在每个循环中循环所有1119个文件。这总共是447600次迭代

假设不能减少循环中的迭代次数,让我们从加快每次迭代开始。
addmember
cmdlet的速度会非常慢,因此通过将哈希表转换为[PSCustomObject]类型的加速器来切换这种方法:

[PSCustomObject]@{
    SearchWord = $Word
    File       = $File.FullName
}
此外,没有理由预先创建一个数组对象,然后将每个文件添加到其中。您可以简单地在变量中捕获foreach循环的输出:

$Results = Foreach ($Word in $Words)
{
...
因此,更快的循环可能如下所示:

$Words = Get-Content -Path $WordList
$Files = Get-ChildItem -Path $Path -Recurse -File

$Results = Foreach ($Word in $Words)
{    
    foreach ($File in $Files)
    {
        if ($File.BaseName -match $Word)
        {
            [PSCustomObject]@{
                SearchWord = $Word
                File       = $File.FullName
            }
        }
    }
}
更简单的方法可能是使用文件数组上的Where对象:

$Results = Foreach ($Word in $Words)
{
    $Files | Where-Object BaseName -match $Word
}

同时尝试这两种方法并测试性能。

因此,如果加速循环不能满足您的需要,请尝试完全删除循环。您可以使用regex并将所有单词连接在一起:

$Words = Get-Content -Path $WordList
$Files = Get-ChildItem -Path $Path -Recurse -File
$WordRegex = $Words -join '|'
$Files | Where basename -match $WordRegex

您是否试图从文件内容中查找
$sw
?这个问题听起来很像,但脚本只显示文件名。您阅读了全部1100个文件,每400个单词都在查找!这种疯狂的语言能一次搜索10个单词吗?然后,您只需要对1100个文件进行40次传递,速度将提高10倍。如果你找到了一个号码,你需要继续搜索文档吗?或者你能在第一次匹配时退出吗?这种疯狂的语言允许并行化吗?你能用Linux来代替这个东西吗?看看,哪个可以使用正则表达式进行更有效的匹配。此外,与多次调用
getchilditem
相比,您可能更高效地先获取所有文件名,然后在内存中检查它们。最后,尝试使用该方法,而不是
新建对象
/
添加成员
,因为管道可能会减慢速度。@MarkSetchell当然
select string
类似于powershell中的
grep
,它可以搜索多个模式以及regexIf如果您有项目中的一段工作代码,并且正在寻找以下领域的开放式反馈:最佳实践和设计模式使用、安全问题、*性能*,在未预料到的情况下保持正确性-然后是提出问题的正确地方。有人能提出这个问题吗?我不能。太好了!我总是忘记-PipelineVariable!谢谢,@MattMcNabb。这是一个方便的特性,但是对它的需求并不经常出现,所以很难记住。谢谢@MattMcNabb的精彩解释。不幸的是,我看到了下面的错误<代码>选择字符串:无法将参数绑定到参数“模式”,因为它是空字符串。在C:\Users\david.craven\Downloads\test.ps1:5 char:39+选择字符串-SimpleMatch-模式$searchWords |+~~~~~~~~~~~~~~~~~~~~~~+CategoryInfo:InvalidData:(:)[选择字符串],参数Bindin gValidationException+FullyQualifiedErrorId:ParameterArgumentValidationErrorEmptyStringNotAll owed,Microsoft.PowerShell.Commands.SelectStringCommand@dcraven:这表明
$searchWords
是空的,而不是包含您的搜索词。多个匹配项的优点是,@LotPings。为了简单起见,我决定将
-List
添加到
Select String
,这将匹配限制为最多出现一次。