Переименование файлов в нижний регистр в Powershell
Я пытаюсь переименовать кучу файлов рекурсивно с помощью PowerShell 2.0. Структура каталогов выглядит следующим образом:
Leaflets
+ HTML
- File1
- File2
...
+ HTMLICONS
+ IMAGES
- Image1
- Image2
- File1
- File2
...
+ RTF
- File1
- File2
...
+ SGML
- File1
- File2
...
я использую следующую команду:
get-childitem Leaflets -recurse | rename -newname { $_.name.ToLower() }
и, похоже, переименовывает файлы, но жалуется на подкаталоги:
Rename-Item : Source and destination path must be different.
я перезагружаю данные ежемесячно с помощью robocopy, но каталоги не меняются, поэтому я могу переименовать их вручную. Есть ли способ получить get-children
чтобы пропустить подкаталоги (например find Leaflets -type f ...
)?
спасибо.
обновление: похоже, что проблема заключается в файлах, которые уже все строчные буквы. Я попытался изменить команду на:
get-childitem Leaflets -recurse | if ($_.name -ne $_name.ToLower()) rename -newname { $_.name.ToLower() }
но теперь Powershell жалуется, что if
не командлета, функции и т. д.
Могу ли я передать вывод get-childitem
до if
заявление?
обновление 2: это работает:
$files=get-childitem Leaflets -recurse
foreach ($file in $files)
{
if ($file.name -ne $file.name.ToLower())
{
rename -newname { $_.name.ToLower() }
}
}
6 ответов
хотя вы уже опубликовали свой собственный ответ, вот вариант:
dir Leaflets -r | % { if ($_.Name -cne $_.Name.ToLower()) { ren $_.FullName $_.Name.ToLower() } }
некоторые моменты:
- dir псевдоним Get-ChildItem (и-r-сокращение от-Recurse).
- % псевдоним ForEach-Object.
- - cne это сравнение с учетом регистра. - ne игнорирует различия в случае.
- $_ как вы ссылка на текущий элемент в цикле ForEach-Object.
- РЕН псевдоним Переименовать Элемент.
- имя, вероятно, предпочтительнее, так как это гарантирует, что вы будете касаться правильного файла.
Если вы хотите исключить каталоги из переименования, вы можете включить что-то вроде:
if ((! $_.IsPsContainer) -and $_.Name -cne $_.Name.ToLower()) { ... }
надеюсь, это поможет продолжить изучение и изучение PowerShell.
имейте в виду, что вы можете напрямую переименовать-Item и использовать Scriptblocks с -NewName
параметр (поскольку он также принимает ввод конвейера) для упрощения этой задачи:
Get-ChildItem -r | Where {!$_.PSIsContainer} |
Rename-Item -NewName {$_.FullName.ToLower()}
и с псевдонимы:
gci -r | ?{!$_.PSIsContainer} | rni -New {$_.FullName.ToLower()}
небольшое дополнение по этому, если вы хотите только обновить имена файлов определенного типа попробуйте это:
get-childitem *.jpg | foreach { if ($_.Name -cne $_.Name.ToLower()) { ren $_.FullName $_.Name.ToLower() } }
это будет только в нижнем регистре jpg-файлов в вашей папке и игнорировать остальные
вам нужно временно переименовать их во что-то другое, а затем назвать их обратно в нижнем регистре.
$items = get-childitem -Directory -Recurse
foreach ($item in $items)
{
if ($item.name -eq $item.name.ToLower())
{
$temp = $item.FullName.ToLower() + "_"
$name = $item.FullName.ToLower()
ren $name $temp
ren $temp $name
}
есть много вопросов с предыдущими данными ответами из-за характера того, как Rename-Item
, трубопровод, цикл и файловая система Windows работает. К сожалению, самое простое (не используя псевдонимы для удобства чтения здесь) решение, которое я нашел для переименовать все файлы и папки внутри данной папки в нижнем регистре это:
Get-ChildItem -Path "/Path/To/You/Folder" -Recurse | Where{ $_.Name -cne $_.Name.ToLower() } | ForEach-Object { $tn="$($_.Name)-temp"; $tfn="$($_.FullName)-temp"; $nn=$_.Name.ToLower(); Rename-Item -Path $_.FullName -NewName $tn; Rename-Item -Path $tfn -NewName $nn -Force; Write-Host "New Name: $($nn)";}
это более idomatic в PowerShell, чтобы использовать where
вместо if
в трубопроводе:
gci -Recurse Leaflets | ? { $_.Name -ne $_.Name.ToLower()) } | % { ren -NewName $_.Name.ToLower() }