Подтвердить что ты не робот

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

Спасибо.

UPDATE: Похоже, что проблема связана с файлами, которые уже имеют все нижний регистр. Я попытался изменить команду:

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() }
    }
}
4b9b3361

Ответ 1

Даже если вы уже разместили свой собственный ответ, вот вариант:

dir Leaflets -r | % { if ($_.Name -cne $_.Name.ToLower()) { ren $_.FullName $_.Name.ToLower() } }

Некоторые моменты:

  • dir - это псевдоним для Get-ChildItem (и -r для -Recurse).
  • % - это псевдоним для ForEach-Object.
  • -cne - это чувствительное к регистру сравнение. -ne игнорирует различия в case.
  • $_ - это то, как вы ссылаетесь на текущий элемент в цикле ForEach-Object.
  • ren - псевдоним для Переименовать элемент.
  • FullName, вероятно, предпочтительнее, поскольку оно гарантирует, что вы будете касаться нужного файла.

Если вы хотите исключить переименование каталогов, вы можете включить что-то вроде:

if ((! $_.IsPsContainer) -and $_.Name -cne $_.Name.ToLower()) { ... }

Надеюсь, это поможет продолжить изучение и исследование PowerShell.

Ответ 2

Имейте в виду, что вы можете напрямую подключиться к пункту "Переименовать" и использовать Scriptblocks с параметром - NewName (потому что он также принимает ввод конвейера) для упрощения этой задачи:

Get-ChildItem -r | Where {!$_.PSIsContainer} | 
                   Rename-Item -NewName {$_.FullName.ToLower()}

и с псевдонимами:

gci -r | ?{!$_.PSIsContainer} | rni -New {$_.FullName.ToLower()}

Ответ 3

небольшая настройка на этом, если вы хотите обновить имена файлов определенного типа, попробуйте это:

get-childitem *.jpg | foreach { if ($_.Name -cne $_.Name.ToLower()) { ren $_.FullName $_.Name.ToLower() } }

это приведет только к нижнему регистру jpg файлов в вашей папке и игнорирует остальные

Ответ 4

Вам необходимо временно переименовать их в другое, а затем назовите их обратно в нижнем регистре.

$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
   }

Ответ 5

В PowerShell более Idomatic использует where вместо if в конвейере:

gci -Recurse Leaflets | 
    ? { $_.Name -ne $_.Name.ToLower()) } | 
    % { ren -NewName $_.Name.ToLower() }