Переименуйте файлы последовательно, и если файл уже существует (конфликт имен), просто увеличьте итератор, чтобы дать файлу новое имя

У меня есть этот код для массового переименования всех файлов .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" и так на каждой итерации.

Я видел этот ответ, но ответчик сделал код слишком длинным, я хочу сделать это как можно короче, но не могу понять, как этого добиться, любая помощь приветствуется.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Обновлено: избавился от ошибочного оператора тестового пути и добавил переименование в 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++
        }
    }
}   

Как я и подозревал, это не переименовывает все файлы с шаблоном vlc-record-2024*.mp4. Он останавливается после переименования нескольких файлов с повторением этой ошибки: Rename-Item : Cannot create a file when that file already exists. Но спасибо за усилия, он переименовывает несколько файлов, но не все из них.

Vicky Dev 19.08.2024 00:28

Извините, в моем описании пути тестирования есть ошибка, позвольте мне ее исправить.

Dom 19.08.2024 09:53
Ответ принят как подходящий

Вероятно, вы могли бы сделать это за один вызов 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
}

Это работает чертовски круто, оно переименовывает все видео, независимо от их количества, большое спасибо!

Vicky Dev 19.08.2024 00:47

@VickyDev рада, что это помогло;)

Santiago Squarzon 19.08.2024 00:49

Другие вопросы по теме