Add -RenamePattern/-RenameReplacement for renaming files before upload

This commit is contained in:
2026-04-16 21:34:20 -05:00
orang tua b2fed6c373
melakukan 6a451044dd
2 mengubah file dengan 69 tambahan dan 3 penghapusan
+43 -3
Melihat File
@@ -43,6 +43,15 @@
.PARAMETER Recurse
Scan subdirectories in LocalPath.
.PARAMETER RenamePattern
Regex pattern to match in the filename for renaming before upload.
Must be used together with -RenameReplacement.
Supports capture groups (e.g. '(.+)\.csv$' with replacement '$1_processed.csv').
.PARAMETER RenameReplacement
Replacement string for the -RenamePattern match. Supports regex capture groups ($1, ${1}, etc.).
Use '$0' to reference the full match.
.PARAMETER DeleteAfterTransfer
Delete local files after successful upload (move behavior).
@@ -60,6 +69,18 @@
.\Send-FilesToSftp.ps1 -LocalPath "C:\exports" -RemotePath "/incoming" `
-HostName "sftp.example.com" -UserName "uploader" -FileFilter '\.csv$'
.EXAMPLE
# Rename files by appending today's date before the extension
.\Send-FilesToSftp.ps1 -LocalPath "C:\exports" -RemotePath "/incoming" `
-HostName "sftp.example.com" -UserName "uploader" `
-RenamePattern '^(.+?)(\.[^.]+)$' -RenameReplacement "`$1_$(Get-Date -Format 'yyyyMMdd')`$2"
.EXAMPLE
# Add a prefix to every uploaded file
.\Send-FilesToSftp.ps1 -LocalPath "C:\exports" -RemotePath "/incoming" `
-HostName "sftp.example.com" -UserName "uploader" `
-RenamePattern '^' -RenameReplacement 'processed_'
.EXAMPLE
# Unattended with saved credentials and move behavior
.\Send-FilesToSftp.ps1 -LocalPath "C:\exports" -RemotePath "/incoming" `
@@ -106,6 +127,10 @@ param(
[string]$KeyFilePath,
[string]$RenamePattern,
[string]$RenameReplacement,
[switch]$Recurse,
[switch]$DeleteAfterTransfer,
@@ -169,11 +194,18 @@ function Find-WinScpDll {
# ── Main ─────────────────────────────────────────────────────────────────────
try {
# ── Validate rename parameters ───────────────────────────────────────
if (($RenamePattern -and -not $RenameReplacement) -or ($RenameReplacement -and -not $RenamePattern)) {
Write-Log "-RenamePattern and -RenameReplacement must be used together." -Level ERROR
exit 1
}
Write-Log "═══ SFTP Transfer Starting ═══"
Write-Log "Local path : $LocalPath"
Write-Log "Remote path : $RemotePath"
Write-Log "File filter : $FileFilter"
Write-Log "Host : ${HostName}:${Port}"
if ($RenamePattern) { Write-Log "Rename : '$RenamePattern' → '$RenameReplacement'" }
if ($DryRun) { Write-Log "*** DRY RUN MODE - No files will be transferred ***" -Level WARN }
# ── Find and load WinSCP ─────────────────────────────────────────────
@@ -228,10 +260,13 @@ try {
if ($DryRun) {
Write-Log "Files that would be transferred:" -Level INFO
foreach ($f in $allFiles) {
$destName = if ($RenamePattern) { $f.Name -replace $RenamePattern, $RenameReplacement } else { $f.Name }
$relativePath = $f.FullName.Substring($LocalPath.TrimEnd('\').Length)
$remoteDest = ($RemotePath.TrimEnd('/') + $relativePath) -replace '\\', '/'
$remoteDir = ($RemotePath.TrimEnd('/') + ($f.DirectoryName.Substring($LocalPath.TrimEnd('\').Length) -replace '\\', '/'))
$remoteDest = "$remoteDir/$destName"
$sizeKB = [math]::Round($f.Length / 1KB, 1)
Write-Log " $($f.FullName)$remoteDest (${sizeKB} KB)"
$renameNote = if ($RenamePattern -and $destName -ne $f.Name) { " [renamed from $($f.Name)]" } else { '' }
Write-Log " $($f.FullName)$remoteDest (${sizeKB} KB)$renameNote"
}
Write-Log "DRY RUN complete. $($allFiles.Count) file(s) would be transferred." -Level SUCCESS
exit 0
@@ -294,8 +329,13 @@ try {
$relativePath = $file.DirectoryName.Substring($LocalPath.TrimEnd('\').Length) -replace '\\', '/'
}
$destName = if ($RenamePattern) { $file.Name -replace $RenamePattern, $RenameReplacement } else { $file.Name }
$targetDir = $RemotePath.TrimEnd('/') + $relativePath
$targetPath = "$targetDir/$($file.Name)"
$targetPath = "$targetDir/$destName"
if ($RenamePattern -and $destName -ne $file.Name) {
Write-Log "Renaming: $($file.Name)$destName"
}
try {
# Ensure subdirectory exists on remote when recursing