Reputation: 2193
I have this code to mass rename all the .mkv & .mp4 files in the specific directory of my choosing:
$i = 0; Get-ChildItem "$env:Userprofile\Videos\Movie_Best_Clips" -Filter "vlc-record-2024*.mp4" -Recurse | %{Rename-Item $_.FullName -NewName ($_.Directory.Name+'_'+'_{0:D4}.mp4' -f $i++)};
$i = 0; Get-ChildItem "$env:Userprofile\Videos\Movie_Best_Clips" -Filter "vlc-record-2024*.mkv" -Recurse | %{Rename-Item $_.FullName -NewName ($_.Directory.Name+'_'+'_{0:D4}.mkv' -f $i++)};
There are multiple directories inside $env:Userprofile\Videos\Movie_Best_Clips
in those folders are the files that match pattern vlc-record-2024*.mp4
or vlc-record-2024*.mkv
.
Now I want to, without making any major code altering changes, include a check for whether a file with same name as the name made by iterator exists or not in the given directory, either before or inside Rename-Item
line.
If such file already exists then just do continue
like behaviour and increment the iterator and subsequently give a fresh name to file, to avoid rename-item errors.
So for example if file with name "MOVIENAME 2024 ENGLISH 1080P.mkv__0002.mp4" already exists(in the same directory as the existing "vlc-record-2024" file* that's to be renamed) then just rename the file in question with "MOVIENAME 2024 ENGLISH 1080P.mkv__0003.mp4" and like that on each and every iteration.
I saw this answer but the answerer has made the code too long, I want to do it in shortest way possible, but can't wrap my head around about how to achieve it, any help is appreciated.
Upvotes: 1
Views: 87
Reputation: 418
Edit: got rid of flawed test-path statement and added wrapped the rename into try-catch for better troubleshooting
Get-ChildItem "C:\Users\kakoscdo-admin\Projekte\new2\logs" -Filter "*mkv" -Recurse | sort CreationTime -Descending| ForEach-Object {
$noNewNameFound = $true
while($noNewNameFound) {
$newName = $_.Directory.Name + '_' + '_{0:D4}.mkv' -f $i
write-host "try renaming $($_.fullname) to $newName"
if (test-path (Join-Path $_.DirectoryName $newname)) {
$i++;
write-host "$newName already exists, try next"
}
else {
write-host "new name not exist yet try renaming"
write-host "$($_.parent)\$newname"
try {
Rename-Item $_.FullName -NewName $newName
if($?) { write-host "successfully renamed" }
$noNewNameFound = $false
} catch {
$noNewNameFound=$true;
write-host "error renaming $_.error, try next name"
}
$i++
}
}
}
Upvotes: 1
Reputation: 60873
You could probably accomplish this in a single Get-ChildItem
call using a hashtable that contains the index for each extension. There is also no need for a ForEach-Object
loop if you use a delay-bind scriptblock.
$i = @{ '.mkv' = 0; '.mp4' = 0 }
$getChildItemSplat = @{
Include = 'vlc-record-2024*.mkv', 'vlc-record-2024*.mp4'
Recurse = $true
Path = "$env:Userprofile\Videos\Movie_Best_Clips"
}
Get-ChildItem @getChildItemSplat | Rename-Item -NewName {
while ($true) {
$name = '{0}_{1:D4}{2}' -f $_.Directory.Name, $i[$_.Extension]++, $_.Extension
if (-not (Test-Path (Join-Path $_.DirectoryName $name))) {
break
}
}
$name
}
Upvotes: 2