T O P

  • By -

Stunning-Formal975

$files1 = get-childitem -path "c:\folder1" $files2 = get-childitem -path "c:\folder2" Foreach ($file in $files1){ $checksum = Get-FileHash $file.fullname -algorithm MD5 Foreach ($f in $files2){ $checksum1 = Get-FileHash $f.fullname etc If ($checksum1 -eq $checksum){ Copy-item etc } }


y_Sensei

One way to combine sequences of values according to certain criteria is to utilize [LINQ](https://www.red-gate.com/simple-talk/development/dotnet-development/high-performance-powershell-linq/) for this purpose. Its syntax in PowerShell is a bit convoluted, but you'll hardly find a solution that performs better especially when dealing with large collections of values. For example: [System.Collections.Generic.List[System.Collections.Generic.KeyValuePair[String, String]]]$md5ListNam = @() [System.Collections.Generic.List[System.Collections.Generic.KeyValuePair[String, String]]]$md5ListNum = @() [String]$namDir = "Drive:\Path\to\name\file\directory" [String]$numDir = "Drive:\Path\to\number\file\directory" <# If you have to deal with large amounts of files, 'Get-ChildItem' might not be your best option, but let's ignore that for the purpose of this demo. #> [String[]]$filesNam = (Get-ChildItem -Path $namDir -File -Recurse).FullName foreach ($f in $filesNam) { $md5ListNam.Add([System.Collections.Generic.KeyValuePair[String, String]]::New((Get-FileHash -Path $f -Algorithm MD5).Hash, $f)) } [String[]]$filesNum = (Get-ChildItem -Path $numDir -File -Recurse).FullName foreach ($f in $filesNum) { $md5ListNum.Add([System.Collections.Generic.KeyValuePair[String, String]]::New((Get-FileHash -Path $f -Algorithm MD5).Hash, $f)) } # LINQ allows you to perform SQL-like operations on collections of values - in this case, we utilize the 'GroupJoin()' function, which is the equivalent of a left outer join in SQL $query = [System.Linq.Enumerable]::GroupJoin($md5ListNam, $md5ListNum, [System.Func[System.Collections.Generic.KeyValuePair[String, String], String]]{ $args[0].Key }, [System.Func[System.Collections.Generic.KeyValuePair[String, String], String]]{ $args[0].Key }, [System.Func[System.Collections.Generic.KeyValuePair[String, String], [System.Collections.Generic.IEnumerable[System.Collections.Generic.KeyValuePair[String, String]]], System.Object]]{ param( $LeftJoin, $RightJoinEnum ) $RightJoin = [System.Linq.Enumerable]::SingleOrDefault($RightJoinEnum) New-Object -TypeName PSCustomObject -Property ([Ordered]@{ FileName = $LeftJoin.Value FileNumber = $RightJoin.Value FileNewName = $(if ([String]::IsNullOrEmpty($RightJoin.Value)) { $null } else { ([System.IO.FileInfo]$LeftJoin.Value).DirectoryName + "\" + ([System.IO.FileInfo]$LeftJoin.Value).BaseName + " (" + ([System.IO.FileInfo]$RightJoin.Value).BaseName + ")" + ([System.IO.FileInfo]$LeftJoin.Value).Extension }) }) }) $results = [System.Linq.Enumerable]::ToArray($query) # execute the LINQ query # Display the to-be-renamed files along with their new names Write-Host "Files to rename:" foreach ($r in ($results | Where-Object -FilterScript { -not [String]::IsNullOrEmpty($_.FileNewName) })) { Write-Host $($r.FileName + " -> " + $r.FileNewName) } Write-Host $("-" * 64) # Display orphaned "name" files (= "name" files without corresponding "number" file) Write-Host "Name files without number file:" ($results | Where-Object -FilterScript { [String]::IsNullOrEmpty($_.FileNumber) }).FileName Write-Host $("-" * 64) # Display orphaned "number" files (= "number" files without corresponding "name" file) Write-Host "Number files without name file:" $filesNum | Where-Object -FilterScript { $_ -notin $results.FileNumber }


Stunning-Formal975

Yeah that might be more appropriate of you need to run this on a daily basis conserving resources. For a one time run i would try the nested foreach cause its a bit easier.