问题描述
我有一个 powershell 查询,它适用于较小的数据量,但我正在尝试针对其中包含多个文件夹和文件的文件夹运行我的 CSV。文件夹大小近800GB,内含180个文件夹。
我想查看文件夹中是否存在文件,我可以在 Windows 中手动搜索文件,并且不会花很长时间返回结果,但我的 CSV 有 3000 行,我不想对 3000 行执行此操作.我的脚本适用于少量数据。
该脚本已运行 6 天,但尚未生成包含数据的文件。它是 0KB,我通过任务调度程序运行它。
脚本如下。
$myFolder = Get-ChildItem 'C:\Test\TestData' -Recurse -ErrorAction
SilentlyContinue -Force
$myCSV = Import-Csv -Path 'C:\Test\differences.csv' | % {$_.'name' -replace "\\",""}
$compare = Compare-Object -ReferenceObject $myCSV -DifferenceObject $myFolder
Write-Output "`n_____MISSING FILES_____`n"
$compare
Write-Output "`n_____MISSING FILES DETAILS____`n"
foreach($y in $compare){
if($y.SideIndicator -eq "<="){
write-output "$($y.InputObject) Is present in the CSV but not in Missing folder."
}
}
然后我创建了另一个脚本,该脚本运行上述脚本并包含一个输出文件命令并与任务调度程序一起运行。 C:\test\test.ps1 |输出文件 'C:\test\Results.csv'
有没有更好的方法来做到这一点?
谢谢
解决方法
有没有更好的方法来做到这一点?
是的!
- 将磁盘上的每个文件名添加到
HashSet[string]
HashSet
类型在确定它是否包含 特定值与否,比Compare-Object
快得多
- 循环遍历您的 CSV 记录,检查每个文件名是否存在于第 1 步的集合中
# 1. Build our file name index using a HashSet
$fileNames = [System.Collections.Generic.HashSet[string]]::new()
Get-ChildItem 'C:\Test\TestData' -Recurse -ErrorAction
SilentlyContinue -Force |ForEach-Object {
[void]$fileNames.Add($_.Name)
}
# 2. Check each CSV record against the file name index
Import-Csv -Path 'C:\Test\differences.csv' |ForEach-Object {
$referenceName = $_.name -replace '\\'
if(-not $fileNames.Contains($referenceName)){
"${referenceName} is present in CSV but not on disk"
}
}
另一种选择是在 Where-Object
过滤器中使用步骤 1 中的散列集:
$csvRecordsMissingFromDisk = Import-Csv -Path 'C:\Test\differences.csv' |Where-Object { -not $fileNames.Contains($_) }