Thank you so much for such a detailed explanation!
Here is my script:
Code: Select all
#Set-PSDebug -Trace 2
# Print the full command line used to run the script
Write-Host "Script was run with the following command:"
Write-Host $MyInvocation.Line
Write-Host ""
# Function to split the input string based on the pattern "space followed by drive letter and a path"
function Split-ArgumentsByPattern {
param (
[string]$inputString
)
# Regular expression pattern to match space followed by drive letter and path
$pattern = '(?<=\s|"|^)([A-Za-z]:\\[^\/\:\*\?\"\<\>\|]+(?= [A-Za-z]:|"|$))'
# Split the string by the pattern
$folders = [regex]::Matches($inputString, $pattern) | ForEach-Object { $_.Value }
# Remove any leading or trailing whitespace from each folder path
$folders = $folders | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne "" }
return $folders
}
# Combine all arguments into a single string
Write-Host "Arguments : $args"
Write-Host ""
#$combinedArgs = $args -join " "
#Write-Host "Combined Arguments: $combinedArgs"
#Write-Host ""
# Split the combined string into individual folder paths
$rootFolders = Split-ArgumentsByPattern -inputString $args #$combinedArgs
# Print each folder path passed in the array
Write-Host "RootFolders from arguments:"
foreach ($folder in $rootFolders) {
Write-Host "- $folder"
}
# Function to update the parent folder's LastWriteTime
function Update-ParentFolderTime {
param (
[string]$folderPath
)
# Get all items (files and subfolders) in the current folder
$items = Get-ChildItem -Path $folderPath -Recurse
# Find the item with the most recent LastWriteTime
$mostRecentItem = $items | Sort-Object LastWriteTime -Descending | Select-Object -First 1
# If there's a most recent item, compare its LastWriteTime with the parent folder
if ($mostRecentItem) {
$parentFolder = Get-Item -Path $folderPath
if ($parentFolder.LastWriteTime -lt $mostRecentItem.LastWriteTime) {
# Update the parent folder's LastWriteTime to the most recent item's LastWriteTime
Write-Host "6. Updating LastWriteTime of the folder '$folderPath' from $($parentFolder.LastWriteTime) to $($mostRecentItem.LastWriteTime)" -ForegroundColor Red
$parentFolder.LastWriteTime = $mostRecentItem.LastWriteTime
} else {
Write-Host "7. The folder '$folderPath' has the most recent LastWriteTime than its child files and subfolders" -ForegroundColor DarkGreen
}
}
}
# Function to recursively process all folders starting from the bottom level
function Process-Folders {
param (
[string]$rootFolder
)
# Get all subfolders
$subfolders = Get-ChildItem -Path $rootFolder -Directory
Write-Host "1. $subfolders = Get-ChildItem -Path $rootFolder -Directory"
Write-Host "2. $subfolders"
foreach ($subfolder in $subfolders) {
# Recursively process subfolders
Write-Host "3. Process-Folders -rootFolder $($subfolder.FullName)"
Process-Folders -rootFolder $subfolder.FullName
}
# Update the currently processed root folder
Write-Host "5. Update-ParentFolderTime -folderPath $rootfolder"
Update-ParentFolderTime -folderPath $rootFolder
}
# Validate that at least one folder is provided as argument
if (-not $rootFolders) {
Write-Host '
--------------------------------------------------------
Please provide one or more root folder paths as arguments.
For example:
.\UpdateFolderModifiedDate.ps1 "C:\path\to\folder"
or
.\UpdateFolderModifiedDate.ps1 C:\path\to\folder
or
.\UpdateFolderModifiedDate.ps1 "C:\path\to\folder" "C:\path\to\another\folder" "C:\path\to\yet\another\folder"
or
.\UpdateFolderModifiedDate.ps1 C:\path\to\folder C:\path\to\another\folder C:\path\to\yet\another\folder
--------------------------------------------------------
'
# If no arguments were provided, prompt the user to enter one or more folder paths
$input = Read-Host 'Or please enter the paths of the folders you want to process (without/with quotes, just separate multiple paths with the space/s).
For example:
"C:\path\to\folder" "C:\path\to\another\folder"
C:\path\to\folder C:\path\to\another\folder
'
# If the user provided folder paths, split them into an array
if ($input) {
$rootFolders = Split-ArgumentsByPattern -inputString $input # -split ",\s*" # Split by comma, allowing for optional spaces
Write-Host "Input: $input"
Write-Host "RootFolders from input: $rootFolders"
} else {
Write-Host "No folder paths provided. Exiting script."
Set-PSDebug -Trace 0
exit 1
}
}
# Loop through each provided folder and process it
foreach ($rootFolder in $rootFolders) {
if (Test-Path $rootFolder) {
Write-Host "RootFolders from arguments: $rootFolders"
Write-Host "Processing folder: $rootFolder"
Process-Folders -rootFolder $rootFolder
} else {
Write-Host "Folder not found: $rootFolder"
}
}
Set-PSDebug -Trace 0
And the button code:
Code: Select all
TOTALCMD#BAR#DATA
powershell.exe -noexit -ExecutionPolicy Bypass "f:\_Downloads\TotalCommander\PlugIns\UpdateFolderModifiedDate-test2.ps1"
'%X%Y%P%S%T%R'
C:\Program Files (x86)\Total Commander\Wcmicons.dll,51
Change the modification date of folders to match the most recent modification date of their child files or subfolders.
-1
I've already tried all variations (with and without spaces and double or single quotes in different positions) that came to my mind without any success
For example:
X%Y%P%S% T%R (i.e. with the space between P%S% and T%R)
When I selected three folders only in the right panel:
Code: Select all
f:\_Downloads\TotalCommander\TweakTC\
f:\_Downloads\TotalCommander\Ultimate File Manager\
f:\_Downloads\TotalCommander\DiskInternals (FileSystemsReader)\
the result is the following:
Code: Select all
FileSystemsReader : The term 'FileSystemsReader' is not recognized as the name of a cmdlet, function, script file, or
operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try
again.
At line:1 char:206
+ ... nager f:\_Downloads\TotalCommander\DiskInternals (FileSystemsReader)T
+ ~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (FileSystemsReader:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Moreover, if I insert a space between P%S% and T%R, and also enclose all parameters in single quotes to avoid the previous error
'X%Y%P%S% T%R'
I get the following:
Code: Select all
Script was run with the following command:
f:\_Downloads\TotalCommander\PlugIns\UpdateFolderModifiedDate-test2.ps1 ' f:\_Downloads\TotalCommander\TweakTC f:\_Downloads\TotalCommander\Ultimate File Manager f:\_Downloads\TotalCommander\DiskInternals (FileSystemsReader)'
As you can see, there is a space between the single quote and the first selected folder.
And the most interesting thing is, if I add a question mark in front of all the parameters
?%X%Y%P%S%T%R
In the dialog box that appears, I see that TC passes the following line in the parameters:
Code: Select all
f:\_Downloads\TotalCommander\TweakTC "f:\_Downloads\TotalCommander\Ultimate File Manager" "f:\_Downloads\TotalCommander\DiskInternals (FileSystemsReader)"
But the script still throws the following error:
Code: Select all
FileSystemsReader : The term 'FileSystemsReader' is not recognized as the name of a cmdlet, function, script file, or
operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try
again.
At line:1 char:205
+ ... anager f:\_Downloads\TotalCommander\DiskInternals (FileSystemsReader)
+ ~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (FileSystemsReader:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException