Ответ 1
Вы были близки:
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace(".mkv.mp4",".mp4")}
В настоящее время у меня есть строка для переименования файлов в папке, в которой я сейчас.
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, но в этом случае это соответствовало моим потребностям.
Вы были близки:
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace(".mkv.mp4",".mp4")}
Существует не известная функция, предназначенная именно для этого сценария. Вкратце, вы можете сделать что-то вроде:
Get-ChildItem -Recurse -Include *.ps1 | Rename-Item -NewName { $_.Name.replace(".ps1",".ps1.bak") }
Это позволяет избежать использования объекта ForEach путем передачи скриптового блока для параметра NewName. PowerShell достаточно умен, чтобы оценить скриптблока для каждого объекта, который получает канал, установив $_ так же, как и с ForEach-Object.
Обратите внимание, что если у вас все еще есть проблема с ошибками, такими как 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$)','' }