26

我正在尝试使用 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不是 cmdlet、函数等。我可以将输出通过管道get-childitem传输到if语句吗?

更新2:这有效:

$files=get-childitem Leaflets -recurse
foreach ($file in $files)
{
    if ($file.name -ne $file.name.ToLower())
    {
        rename -newname { $_.name.ToLower() }
    }
}
4

8 回答 8

30

即使您已经发布了自己的答案,这里有一个变体:

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

几点:

  • dirGet-ChildItem的别名(-r 是 -Recurse 的缩写)。
  • %ForEach-Object的别名。
  • -cne是区分大小写的比较。-ne忽略大小写差异。
  • $_是您在 ForEach-Object 循环中引用当前项目的方式。
  • renRename-Item的别名。
  • FullName可能是首选,因为它可以确保您将接触到正确的文件。

如果您想排除目录被重命名,您可以包括以下内容:

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

希望这有助于继续学习和探索 PowerShell。

于 2010-09-29T16:13:23.367 回答
18

请记住,您可以直接通过管道连接到 Rename-Item 并使用带有 -NewName参数的 Scriptblocks(因为它也接受管道输入)来简化此任务:

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

并带有别名:

gci -r | ?{!$_.PSIsContainer} | rni -New {$_.FullName.ToLower()}
于 2010-09-29T16:51:50.657 回答
2

对此稍作调整,如果您只想更新特定类型文件的名称,请尝试以下操作:

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

这只会小写您文件夹中的 jpg 文件并忽略其余文件

于 2013-10-15T14:41:13.727 回答
2

您需要暂时将它们重命名为其他名称,然后将它们全部重新命名为小写。

$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
   }
于 2016-09-07T16:43:44.923 回答
2

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)";}
于 2018-06-19T09:38:36.727 回答
0

在 PowerShell 中使用where而不是if在管道中使用更符合规范:

gci -递归传单|
    ? { $_.Name -ne $_.Name.ToLower()) } |
    % { ren -NewName $_.Name.ToLower() }
于 2010-10-11T01:49:38.317 回答
0

Jay Bazuzi 对答案的一个小而重要的更正。如果 where 部分应该返回任何内容,则必须使用-cne(区分大小写不等于)运算符。

此外,我发现需要存在 Path 参数。这个版本在我的设置中工作:

gci -Recurse | 
    ? { $_.Name -cne $_.Name.ToLower() } | 
    % { ren $_.Name -NewName $_.Name.Tolower()  }
于 2020-02-19T15:41:01.877 回答
0

对于所有关注此主题的人;以下行也可用于降低文件和目录。

Get-ChildItem -r  | Rename-Item -NewName { $_.Name.ToLower().Insert(0,'_') } -PassThru |  Rename-Item -NewName { $_.Name.Substring(1) }

主帖:https ://stackoverflow.com/a/70559621/4165074

于 2022-01-03T20:53:28.250 回答