J'ai actuellement une ligne pour renommer par lots des fichiers dans un dossier dans lequel je suis actuellement.
dir | foreach { move-item -literal $_ $_.name.replace(".mkv.mp4",".mp4") }
Ce code fonctionne parfaitement pour n'importe quel répertoire dans lequel je suis actuellement, mais ce que je veux, c'est exécuter un script à partir d'un dossier parent qui contient 11 dossiers enfants. Je peux accomplir ma tâche en accédant à chaque dossier individuellement, mais je préfère exécuter le script une fois et en finir avec lui.
J'ai essayé ce qui suit:
get-childitem -recurse | foreach { move-item -literal $_ $_.name.replace(".mkv.mp4",".mp4") }
Quelqu'un peut-il m'indiquer ici la bonne direction? Je ne connais pas du tout Powershell, mais cela correspondait à mes besoins dans ce cas.
Vous étiez proche:
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace(".mkv.mp4",".mp4")}
Il existe une fonctionnalité peu connue qui a été conçue exactement pour ce scénario. En bref, vous pouvez faire quelque chose comme:
Get-ChildItem -Recurse -Include *.ps1 | Rename-Item -NewName { $_.Name.replace(".ps1",".ps1.bak") }
Cela évite d'utiliser ForEach-Object en passant un bloc de script pour le paramètre NewName. PowerShell est suffisamment intelligent pour évaluer le bloc de script pour chaque objet qui est canalisé, en définissant $ _ comme il le ferait avec ForEach-Object.
Notez que si vous rencontrez toujours un problème avec des erreurs comme Cannot rename because item at '...' does not exist.
, vous travaillez peut-être avec des chemins très longs et/ou des chemins avec des caractères "spécialement interprétés" comme des crochets (c'est-à-dire [
]
).
Pour de tels scénarios, utilisez -LiteralPath
/-PSPath
avec le préfixe spécial \\?\
(pour les chemins UNC, vous voudrez utiliser le préfixe \\?\UNC\
) pour les chemins jusqu'à 32k caractères. Je suggère également de filtrer tôt (avec Get-ChildItem
) pour de meilleures performances (moins Rename-Item
les appels sont meilleurs).
$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$)','' }