Recursively renaming files with Powershell

流过昼夜 提交于 2020-01-09 06:47:07

问题


I currently have a line to batch rename files in a folder that I am currently in.

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

This code works perfectly for whatever directory I'm currently in, but what I want is to run a script from a parent folder which contains 11 child-folders. I can accomplish my task by navigating to each folder individually, but I'd rather run the script once and be done with it.

I tried the following:

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

Can anyone please point me in the right direction here? I'm not very familiar with Powershell at all, but it suited my needs in this instance.


回答1:


You were close:

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



回答2:


There is a not well-known feature that was designed for exactly this scenario. Briefly, you can do something like:

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

This avoids using ForEach-Object by passing a scriptblock for the parameter NewName. PowerShell is smart enough to evaluate the scriptblock for each object that gets piped, setting $_ just like it would with ForEach-Object.




回答3:


Note that if you are still having issue with errors like Cannot rename because item at '...' does not exist., you may be working with some super long paths and/or paths with 'specially-interpreted' characters like square brackets (i.e. [ ]).

For such scenarios, use -LiteralPath/-PSPath along with the special prefix \\?\ (for UNC paths you will want to use the prefix \\?\UNC\) for paths up to 32k characters. I also suggest filtering early (with Get-ChildItem) for improved performance (less Rename-Item calls are better).


$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$)','' }


来源:https://stackoverflow.com/questions/21611551/recursively-renaming-files-with-powershell

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!