Переименование файлов в нижний регистр в 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() }