Add -RenamePattern/-RenameReplacement for renaming files before upload

此提交包含在:
2026-04-16 21:34:20 -05:00
父節點 b2fed6c373
當前提交 6a451044dd
共有 2 個檔案被更改,包括 69 行新增3 行删除
+26
查看文件
@@ -42,6 +42,8 @@ The script auto-searches these locations in order:
| `-CredentialFile` | No | — | Path to saved credential XML (see below) |
| `-KeyFilePath` | No | — | Path to SSH private key (`.ppk`) |
| `-SshHostKeyFingerprint` | No | — | SSH host key fingerprint for verification |
| `-RenamePattern` | No | — | Regex pattern to match in filename for renaming before upload |
| `-RenameReplacement` | No | — | Replacement string for `-RenamePattern` (supports capture groups like `$1`) |
| `-Recurse` | No | `false` | Scan subdirectories |
| `-DeleteAfterTransfer` | No | `false` | Delete local files after successful upload |
| `-DryRun` | No | `false` | Preview transfers without uploading |
@@ -125,6 +127,30 @@ The `-FileFilter` parameter uses PowerShell regex (case-insensitive by default).
-Recurse -FileFilter '\.pdf$'
```
## Renaming Files Before Upload
Use `-RenamePattern` (regex) and `-RenameReplacement` together to rename files on the remote side without touching the local files.
| Goal | Pattern | Replacement |
|------|---------|-------------|
| Add date before extension | `'^(.+?)(\.[^.]+)$'` | `'${1}_20260416${2}'` |
| Add prefix | `'^'` | `'processed_'` |
| Add suffix before extension | `'^(.+?)(\.[^.]+)$'` | `'${1}_done${2}'` |
| Strip `_draft` from name | `'_draft'` | `''` |
| Replace spaces with underscores | `' '` | `'_'` |
Rename uses PowerShell's `-replace` operator (regex, case-insensitive). The local file is **not** modified — only the remote destination path changes.
### Add today's date to every filename
```powershell
$date = Get-Date -Format 'yyyyMMdd'
.\Send-FilesToSftp.ps1 -LocalPath "C:\exports" -RemotePath "/incoming" `
-HostName "sftp.example.com" -UserName "uploader" `
-RenamePattern '^(.+?)(\.[^.]+)$' -RenameReplacement "${date}_`$1`$2"
```
> **Tip:** Use `-DryRun` first to preview the renamed remote paths before committing to the transfer.
## SSH Host Key Fingerprint
For production use, always provide the host key fingerprint to prevent MITM attacks:
+43 -3
查看文件
@@ -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