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