使用Powershell递归重命名文件

时间:2014-02-06 18:55:41

标签: powershell rename

我目前有一行批量重命名我目前所在文件夹中的文件。

dir | foreach { move-item -literal $_ $_.name.replace(".mkv.mp4",".mp4") }

此代码适用于我当前所在的目录,但我想要的是从包含11个子文件夹的父文件夹运行脚本。我可以通过单独导航到每个文件夹来完成我的任务,但我宁愿运行一次脚本并完成它。

我尝试了以下内容:

get-childitem -recurse | foreach { move-item -literal $_ $_.name.replace(".mkv.mp4",".mp4") }

有谁能请我指出正确的方向吗?我根本不熟悉Powershell,但在这种情况下它符合我的需要。

3 个答案:

答案 0 :(得分:32)

有一个鲜为人知的功能是专为这种情况而设计的。简而言之,您可以执行以下操作:

Get-ChildItem -Recurse -Include *.ps1 | Rename-Item -NewName { $_.Name.replace(".ps1",".ps1.bak") }

这可以通过传递参数NewName的scriptblock来避免使用ForEach-Object。 PowerShell足够聪明,可以为每个被管道对象评估scriptblock,设置$ _就像使用ForEach-Object一样。

答案 1 :(得分:25)

你很亲密:

Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.Name.replace(".mkv.mp4",".mp4")}

答案 2 :(得分:0)

请注意,如果您仍然遇到Cannot rename because item at '...' does not exist.之类的错误,您可能正在处理某些超长路径和/或带有“特殊解释”字符的路径,例如方括号(即[ ])。

在这种情况下,请将-LiteralPath / -PSPath与特殊前缀\\?\(对于UNC路径,您将要使用前缀\\?\UNC\)一起使用,直至32k个字符。我还建议尽早过滤(使用Get-ChildItem)以提高性能(较少的Rename-Item调用会更好)。


$path = 'C:\Users\Richard\Downloads\[Long Path] THE PATH TO HAPPINESS (NOT CLICKBAIT)\...etc., etc.'
# -s is an alias for -Recurse
# -File for files only
# gci, dir, and ls are all aliases for Get-ChildItem
#   Note that among the 3, only `gci` is ReadOnly.
gci -s -PSPath $path -File -Filter "*.mkv.mp4" |
    # ren, rni are both aliases for Rename-Item
    #   Note that among the 2, only `rni` is ReadOnly.
    # -wi is for -WhatIf (a dry run basically). Remove this to actually do stuff.
    # I used -replace for regex (for excluding those super rare cases)
  rni -wi -PSPath { "\\?\$($_.FullName)" } -NewName { $_.Name -replace '\.mkv(?=\.mp4$)','' }