Подтвердить что ты не робот

Рекурсивно переименование файлов с помощью Powershell

В настоящее время у меня есть строка для переименования файлов в папке, в которой я сейчас.

dir | foreach { move-item -literal $_ $_.name.replace(".mkv.mp4",".mp4") }

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

Я попробовал следующее:

get-childitem -recurse | foreach { move-item -literal $_ $_.name.replace(".mkv.mp4",".mp4") }

Может ли кто-нибудь указать мне в правильном направлении? Я вообще не очень хорошо знаком с Powershell, но в этом случае это соответствовало моим потребностям.

4b9b3361

Ответ 1

Вы были близки:

Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace(".mkv.mp4",".mp4")}

Ответ 2

Существует не известная функция, предназначенная именно для этого сценария. Вкратце, вы можете сделать что-то вроде:

Get-ChildItem -Recurse -Include *.ps1 | Rename-Item -NewName { $_.Name.replace(".ps1",".ps1.bak") }

Это позволяет избежать использования объекта ForEach путем передачи скриптового блока для параметра NewName. PowerShell достаточно умен, чтобы оценить скриптблока для каждого объекта, который получает канал, установив $_ так же, как и с ForEach-Object.

Ответ 3

Обратите внимание, что если у вас все еще есть проблема с ошибками, такими как Cannot rename because item at '...' does not exist. , вы можете работать с некоторыми сверхдлинными путями и/или путями со "специально интерпретированными" символами, такими как квадратные скобки (то есть [ ]).

Для таких сценариев используйте -LiteralPath/-PSPath вместе со специальным префиксом \\?\ (Для путей UNC вы хотите использовать префикс \\?\UNC\) для путей длиной до 32 тыс. Символов. Я также предлагаю фильтровать заранее (с Get-ChildItem) для повышения производительности (чем меньше вызовов Rename-Item, тем лучше).


$path = 'C:\Users\Richard\Downloads\[Long Path] THE PATH TO HAPPINESS (NOT CLICKBAIT)\...etc., etc.'
# -s is an alias for -Recurse
# -File for files only
# gci, dir, and ls are all aliases for Get-ChildItem
#   Note that among the 3, only 'gci' is ReadOnly.
gci -s -PSPath $path -File -Filter "*.mkv.mp4" |
    # ren, rni are both aliases for Rename-Item
    #   Note that among the 2, only 'rni' is ReadOnly.
    # -wi is for -WhatIf (a dry run basically). Remove this to actually do stuff.
    # I used -replace for regex (for excluding those super rare cases)
  rni -wi -PSPath { "\\?\$($_.FullName)" } -NewName { $_.Name -replace '\.mkv(?=\.mp4$)','' }