Home > Software design >  Powershell Compare Files from multiple subfolders
Powershell Compare Files from multiple subfolders

Time:02-16

I am trying to create a powershell to compare FILE SIZE from multiple subfolders

Today's files Folder Structure:

  • TodaysFolder as a ROOT FOLDER
  • TodaysFolder/Business/FolderA/ csv files
  • TodaysFolder/Business/FolderB/ csv files

I want to compare today's csv file Size from multiple files / subfolders based on yesterday's data

  • Reference Folder Structure:
  • ArchiveFolder/YesterdayDate/Business/FolderA/ CSV files
  • ArchiveFolder/YesterdayDate/Business FolderA/ CSV files

Also I plan to implement a condition if file size is <= 5 %, PASS If file size is > = 10 % size, FAIL

I will post the current code in a few, but just trying to get some ideas and guidance for this project.


$TodayPath =  "\\TodaysFolder\Business/FolderA\"
$TodayFiles = get-childitem $TodayPath  -Exclude Archive -Verbose | 
? {! $_.PSIsContainer} |
Select-Object  Name, @{Name='File Size'; Expression={([string]([int]($_.Length / 1KB)))   " KB"}} 


$archiveFolder = (get-date).AddDays(-1).ToString('yyyyMMdd')
$archiveFolderPath  = "\ArchiveFolder\YesterdayDate\Business\FolderA"

$ArchiveFiles =  get-childitem $archiveFolderPath  -Exclude Archive -Verbose | 
? {! $_.PSIsContainer} |
Select-Object  Name, @{Name='File Size'; Expression={([string]([int]($_.Length / 1KB)))   " KB"}} 


write-host $todayPath -ForegroundColor green
$TodayFiles

write-host "---------------------------" -ForegroundColor Red

write-host $archiveFolderPath -ForegroundColor yellow
$ArchiveFiles



Thanks

CodePudding user response:

Use Group-Object to group your file lists by shared file name and process each group in a ForEach-Object command, where you can compare file sizes.

Note:

  • The exact requirements regarding pass / fail based on the percentage of file-size changes aren't clear at this point and neither is whether the calculations should be based on size of today's file or the corresponding archive file.

  • The code below assumes that today's files as the basis; see the source-code comments for how to change that.

  • The pass / fail logic is limited to passing size-change ratios less than or equal to .05 (5%).

  • A custom object summarizing the comparison is output; it outputs rounded numbers for the sizes and percentages, but you can easily convert that to formatted strings, as shown in the question.

# Determine $TodayPath and $ArchivePath
# ... 

# Note the use -Filter *.csv to limit processing to CSV files.
# Also, since 'Archive' presumably refers to a *directory* to
# exclude, -Exclude Archive is then not necessary.
# There is no need to select a subset of properties with Select-Object
# at this point.
$todayFiles = Get-ChildItem $todayPath -Filter *.csv

$archiveFiles = Get-ChildItem $archiveFolderPath -Filter *.csv

# Group the two lists by shared file name, and process each group.
[array] $todayFiles   $archiveFiles | Group-Object Name | ForEach-Object {

  if ($_.Count -eq 1) {
    # File at hand exists only in *one* location - either only in today
    # location or only in the archive location.
    Write-Warning "File has no counterpart: $($_.Group[0].FullName)"
    return
  }

  # Calculate the size change.
  $refIndex = 0  # Base calculation on today's files; change to 1 for archive files 
  $otherIndex = (0, 1)[$refIndex -eq 0]
  $refSize = $_.Group[$refIndex].Length
  $sizeDelta = $_.Group[$otherIndex].Length - $refSize
  $sizeDeltaRatio = $sizeDelta / $refSize

  # Construct and output a custom object with the properties of interest.
  [pscustomobject] @{
    Name = $_.Group[0].Name
    SizeInKb = [Math]::Round($refSize / 1kb, 2)
    SizeDeltaPercentage = [Math]::Round($sizeDeltaRatio * 100, 2)
    Pass = $sizeDeltaRatio -le .05
  }

}
  • Related