I have a script (below) which works perfectly when run on one test directory on a network drive, but is not fully accurate when modified to be run on all the directories (27 in total) on the same drive it is intended to be run on. The script's purpose is to retain the most up-to-date file as determined either; by virtue of the fact that that the file has never been superseded*, or, by any numeric value that may appear between the 3rd and 4th underscore (SECTION) of the file name.
File name format = NAME_DATE_SEQUENCE(reinserted in file as a 3-digit-numer)_SECTION_SEGMENT_SEQUENCE
For example if script encounters the following files in folder X of any of the directories..:
Name_20240301_001_SectionName_SegmentName_1.pdf and Name_20240301_001_SectionName2_SegmentName_1.pdf
.. it should retain the file with the greatest value apparent in the SECTION field and move any files that match the non-numeric part of the SECTION as well as NAME, DATE, SEQUENCE and SEGMENT, but have lesser or no numeric values in the SECTION, to a specific folder to be checked.
- Some files will never be superseded, therefore will have no file that is a perfect match for all fields but the SECTION, and these need to be retained too.
So when I add all 27 directories I want this to apply to, do I need to duplicate the following script for each directory to help it proceed one directory at a time if resources are an issue, or is there some other way to list all required directories and apply it recursively whilst still keeping it accurate?
Script:
function Get-SectionNumber {
param([string]$fileName)
$parts = $fileName -split '_'
if ($parts.Count -ge 4) {
$sectionPart = $parts[3]
$match = [regex]::Match($sectionPart, '(\d+)')
if ($match.Success) {
return [int]$match.Value
}
}
return $null
}
function Get-SectionNonNumeric {
param([string]$fileName)
$parts = $fileName -split '_'
if ($parts.Count -ge 4) {
$sectionPart = $parts[3]
$match = [regex]::Match($sectionPart, '(\D+)')
if ($match.Success) {
return $match.Value
}
}
return $null
}
$sourceDirectory = "Drive:\Path1\Path1......"
$CheckDeletedDirectory = "Drive:\Path2\Path2......"
$files = Get-ChildItem -Path $sourceDirectory -File -Recurse
portion of the section for grouping
$groupedFiles = $files | Group-Object { ($_.Name -split '_', 4)[0..2] -join '_' + '_' + (Get-SectionNonNumeric $_.Name) }
foreach ($group in $groupedFiles) {
$sortedGroup = $group.Group | Sort-Object @{Expression={Get-SectionNumber $_.Name}; Descending=$true}
$topFile = $sortedGroup[0]
$sortedGroup[1..($sortedGroup.Count - 1)] | ForEach-Object {
Move-Item -Path $_.FullName -Destination $catchDirectory -Force
Write-Host "Moved $($file.FullName) to $CheckDeletedDirectory"
}
Write-Host "Retained file: $($topFile.FullName)"
}
Tried adding in all directories I want this run on, (27 in total)... changing $sourceDirectory to $sourceDirectories in case that made a difference What has me stumped is it initially ran perfectly on my C:\ drive with a much more simplistic mock directory/folder structure... and had also worked on the network drive it is intended to run on using a mock up example of the same directory depth structure present there, albeit for just 2 folders containing files. The only differences between successful and unsuccessful runs are the number of directories, subfolders and files involved.