J'essaie de renommer un grand nombre de fichiers, tous situés dans un dossier mais dans différents sous-dossiers. Les fichiers doivent être renommés afin que leur nom se compose du nom du dossier + le nom du fichier d'origine. Je me demande si vous pouvez ajouter des instructions conditionnelles afin que le nom du fichier ne change pas si le nom du fichier contient déjà le nom du dossier. Le code ci-dessous remplit la fonction de renommer les fichiers mais ne contient pas l'instruction if.
dir -recurse | if($_.Name -contains $_.Directory.Name) {Rename-Item -NewName {$_.Directory.Name + " - " + $_.Name}}
Le code ci-dessous est un exemple de ce à quoi j'imagine le code:
XXX
3 Réponses :
Cela devrait le faire:
$rootFolder = 'D:\test'
Get-ChildItem -Path $rootFolder -File -Recurse | ForEach-Object {
$folder = $_.Directory.Name
if (!($_.Name.StartsWith($folder))) { $_ | Rename-Item -NewName ('{0} - {1}' -f $folder, $_.Name) }
}
La réponse de Theo fonctionne bien, mais il existe une alternative qui est à la fois plus simple et plus performante sur le plan conceptuel nettement mieux:
Vous pouvez profiter du fait que passer un nom de fichier inchangé à -NewName est un no-op tranquille , afin que vous puissiez placer toute votre logique dans le bloc de script -NewName :
Get-ChildItem -File -Recurse |
Rename-Item -NewName {
if ($_.Name -like ($_.Directory.Name + ' - *') { # already renamed
$_.Name # no change
}
else { # rename
$_.Directory.Name ' - ' + $_.Name
}
} -WhatIf
-WhatIf prévisualise l'opération de changement de nom; supprimez-le pour effectuer un changement de nom réel.
Plutôt que d'utiliser un appel ForEach-Object avec un appel Rename-Item imbriqué dans son bloc de script - ce qui signifie que Rename-Item est appelé une fois pour chaque fichier d'entrée - cette solution utilise un pipeline unique avec un unique em> Appel de Rename-Item , où le nouveau nom (s'il est modifié) est déterminé via un bloc de script delay-bind - voir cette réponse pour plus de détails.
Je l'ai essayé d'une manière proche de la façon dont la question a été posée. J'aimerais ne pas avoir à ajouter un autre foreach.
dir -recurse -file | % {
if(-not ($_.Name.contains($_.Directory.Name))) {
Rename-Item $_.fullname -NewName ($_.Directory.Name + ' - ' + $_.Name) -whatif
}
}
Ou comme ça
dir -recurse -file | & {
foreach ($i in $input) {
if(-not ($i.Name.contains($i.Directory.Name))) {
Rename-Item $i.fullname -NewName ($i.Directory.Name + ' - ' + $i.Name) -whatif
}
}
}
Double possible de PowerShell et l'opérateur -contains
siles instructions ne sont pas lues à partir du pipeline. Utilisez plutôtWhere-Object.Vous voulez dire si -pas ... .contient () ...