Reputation: 1607
So I'm trying to rename a bunch of MSSQL backups that come out like:
DBName_backup_2017_12_20_564451321_567987465.bak
To Something like
DBName.bak
But also have a safety check to ensure that if DBName.bak
is already taken it'll do DBName_1.bak
. Where 1 will be an incremental variable until there is a valid unused filename.
I was able to do it with the following code:
Get-ChildItem *_*.bak | % {
# Set the new name, replace everything after the first underscore '_' with
# '.bak'
$newName = &{$_.Name -replace $_.Name.Substring($_.Name.IndexOf("_")), '.bak'}
# Check if new name exists
for ($cnt = 1; (Test-Path $newName) -eq $true; $cnt++) {
# If it already exists add '_' and a number check again until unused
# filename is found
$newName = &{$newName -replace '.bak', "_$cnt.bak"}
}
# Rename file to new filename. Uncomment WhatIf for testing.
Rename-Item -Path $_ -NewName $newName #-WhatIf
}
What I'm trying to do now, is to one line it with piping, but am having no luck. Particularly getting the loop to run with the Test-Path
check. Does anyone know how I could one like this?
Upvotes: 0
Views: 47
Reputation: 200233
Simple:
$cnt = 0; Get-ChildItem *_*.bak | Rename-Item -NewName {
($_.BaseName -replace '_.*', '_') + $script:cnt++ + $_.Extension
} -WhatIf
If you just want to (re)number files with duplicate database names you can't truly one-line the thing. You need something like this:
Get-ChildItem *_*.bak | ForEach-Object {
$basename = $_.BaseName -replace '_.*'
$newname = $basename + $_.Extension
$script:cnt = 1
while (Test-Path $newname) {
$newname = $basename + '_' + $script:cnt++ + $_.Extension
}
Rename-Item -NewName $newname -WhatIf
}
However, in PowerShell you can separate statements with both newlines and semicolons, so you can still merge all of the above into one line. Like this:
Get-ChildItem *_*.bak | ForEach-Object {$basename = $_.BaseName -replace '_.*'; $newname = $basename + $_.Extension; $script:cnt = 1; while (Test-Path $newname) {$newname = $basename + '_' + $script:cnt++ + $_.Extension}; Rename-Item -NewName $newname -WhatIf}
I don't normally recommend doing this, though, because it makes code unnecessarily hard to read and debug.
Either way, remove the the chicken switch after you verified renaming would work as desired.
Upvotes: 1