У меня есть этот код для массового переименования всех файлов .mkv и .mp4 в выбранном мной каталоге:
$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++)};
Внутри есть несколько каталогов $env:Userprofile\Videos\Movie_Best_Clips
, в этих папках находятся файлы, соответствующие шаблону vlc-record-2024*.mp4
или vlc-record-2024*.mkv
.
Теперь я хочу, не внося каких-либо серьезных изменений в код, включить проверку того, существует ли файл с тем же именем, что и имя, созданное итератором, или нет в данном каталоге, до или внутри строки Rename-Item
.
Если такой файл уже существует, просто выполните поведение continue
Like и увеличьте итератор, а затем дайте файлу новое имя, чтобы избежать ошибок переименования элемента.
Так, например, если файл с именем «MOVIENAME 2024 ENGLISH 1080P.mkv__0002.mp4» уже существует (в том же каталоге, что и существующий файл «vlc-record-2024» *, который необходимо переименовать), просто переименуйте соответствующий файл с помощью « MOVIENAME 2024 ENGLISH 1080P.mkv__0003.mp4" и так на каждой итерации.
Я видел этот ответ, но ответчик сделал код слишком длинным, я хочу сделать это как можно короче, но не могу понять, как этого добиться, любая помощь приветствуется.
🤔 А знаете ли вы, что...
PowerShell поддерживает объектно-ориентированное программирование и работу с объектами .NET.
Обновлено: избавился от ошибочного оператора тестового пути и добавил переименование в try-catch для лучшего устранения неполадок.
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 allready 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++
}
}
}
Вероятно, вы могли бы сделать это за один вызов Get-ChildItem
, используя хеш-таблицу, содержащую индекс для каждого расширения. Также нет необходимости в цикле ForEach-Object
, если вы используете скриптовый блок с задержкой привязки.
$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
}