0

I've run into the issue I know has been addressed several times here previously but I'm not overly familiar with PS scripts or regular expressions and I'm struggling to implement a fix here.

Basically, I'd be very happy if this line of my script would work:

Get-childItem *.* -recurse -force | % {rename-item $_.name ($_.name -replace '(\d{2}) \[(\d{1})x(\d{2})\]','$1 s0$2e$3')}

And example file name would be "24 [1x01].avi" and should instead be named "24 s01e01.avi" - I'm trying to tidy up my media collection :)

I know the reason it doesn't is the square brackets in the file names. I think i have to move the files to a temp location, changing the name while doing so and then move back. My difficulty is that I haven't been able to find an example of this using the regular expression and I haven't been able to get this to work.

Also, is there a better workaround than this available yet? The bug on Microsoft Connect is closed as fixed?

Thanks!

michaelekins
  • 529
  • 1
  • 7
  • 23

4 Answers4

2

I think your regular expressions might make more sense (to you), especially as a beginner, if you used "named groups" (a regular expression concept). I've modified your regular expression slightly to take this into account. You should really get familiar with regular expression terminology though, to ensure that you can update your regex to work in all scenarios.

"24 [1x01].avi" -replace '(?<ShowName>.*) \[(?<Season>\d{1})x(?<Episode>\d{2})\]','${ShowName} s0${Season}e${Episode}';

Result:

24 s01e01.avi

Can you give an example of a file name that doesn't work?

EDIT: Attaching example script. Let me know if this works for you.

# 1. Define a test folder path
$RootPath = "$env:SystemDrive\test";
# 2. Create the folder
mkdir -Path $RootPath;
# 3. Create a test file
Set-Content -Path "$RootPath\24 [1x01].txt" -Value '';
# 4. Get a list of files in the directory
$FileList = Get-ChildItem -Path $RootPath;

foreach ($File in $FileList) {
    # 5. Fix up the name of each file
    $NewName = $File.Name -replace '(?<ShowName>.*) \[(?<Season>\d{1})x(?<Episode>\d{2})\]','${ShowName} s0${Season}e${Episode}';
    # 6. Rename the file
    Move-Item -Path $File.FullName -Destination ((Split-Path -Path $File.FullName -Parent) + $NewName);
}
  • Thanks for the tip, it's definitely helped me understand the groupings better :) I'm still getting issues with my files though. Filename is "24 [1x01].avi" and I get error message "Cannot rename because item at '24 [1x01].avi' does not exist." Same error with both my regex pattern and with the one you kindly provided. – michaelekins Dec 31 '13 at 00:55
  • Edited answer with example script. That works just fine for me in PowerShell version 4.0. Since there shouldn't be any substantial changes to the filesystem stuff between version 3.0 and 4.0, this should work on either Windows 8 or 8.1. What version of PowerShell are you running? –  Dec 31 '13 at 01:01
  • That didn't work either, but it looks like I discovered my issue - version is 2.0 so looks like I need an update :) I'll report back once I've completed. Thanks! – michaelekins Dec 31 '13 at 01:10
  • Awesome - Make sure you grab the Microsoft .NET Framework 4.5.1 before installing PowerShell version 4.0. Are you running Windows 7 with Service Pack 1? –  Dec 31 '13 at 01:16
  • Download link for Windows Management Framework Core 4.0 package: http://www.microsoft.com/en-us/download/details.aspx?id=40855 If you're running Windows 7, it's "6.1" –  Dec 31 '13 at 01:18
  • Thanks for the help! I'm now updated to 4.0 but still having problems. I can't get your example script above to work - run as is, I get the message "Set Content : An object at the specified path C:\test\24 [1x01].txt does not exist or has been filtered by the -Include or -Exclude parameter". I instead manually dropped the file "24 [1x01]" to the test folder and commented out the mkdir and Set-Content lines. Now, the script runs without error but doesn't rename the file. While troubleshooting I discovered that there was a "\" missing so made a slight edit: "$NewName = "\" + " but still no luck. – michaelekins Dec 31 '13 at 11:15
  • Sorry - ran out of characters in previous comment. My loop reads: foreach ($File in $FileList) { # 5. Fix up the name of each file $NewName = "\" + $File.Name -replace '(?.*) \[(?\d{1})x(?\d{2})\]','${ShowName} s0${Season}e${Episode}'; # 6. Rename the file Write-Host ((Split-Path -Path $File.FullName -Parent) + $NewName) Move-Item -Path $File.FullName -Destination ((Split-Path -Path $File.FullName -Parent) + $NewName); } The Write-Host gives me "C:\test\24 s01e01.txt" as required but the file is still names "24 [1x01].txt" in directory. Any ideas? – michaelekins Dec 31 '13 at 11:19
1

powershell Rename-Item fail to rename

If you are running PS 3+ add -LiteralPath switch to your rename:

Leonardo
  • 11
  • 1
1

One of the easiest ways to handle the Special Characters (such as square/block brackets[]) in the file-names, is to simply use the -LiteralPath parameter.

Error: When attempting to rename files or folders that contain square/block brackets [], the standard error message that PowerShell returns is "file not found", which is not accurate.

Reason: Windows still uses old fashioned 8.3 format short-file-names (max 8 chars with limited allowed chars) unfortunately PowerShell's -Path parameter (even in version 5.1) uses these internal names.

Solution: Use the -LiteralPath argument, available for most cmdlets (including Get-ChildItem or Rename-Item etc.)

Examples: Depicting handling of files or folders that contain square/block brackets []:

Get-ChildItem -LiteralPath "test[1].txt";
Test-Path -LiteralPath "C:\dir\test[1].txt";
Rename-Item -LiteralPath "test[1].txt"  "test[2].txt";

Note: In PowerShell version below 3.0, to rename files/directories containing special characters, use Move-Item with -LiteralPath, instead of Rename-Item cmdlet because Rename-Item didn't have -LiteralPath in PS version 2.0 (or below).

Eddie Kumar
  • 1,216
  • 18
  • 20
0

Thanks to pointers from @Trevor Sullivan I was able to get the desired results by:

  • Updating to the most recent version of PowerShell (download link available in the comments)

  • Edited the script to the following:

    Get-childItem *.* -recurse -force | Move-Item -Destination {$_ -replace '(\d{2}) \[(\d{1})x(\d{2})\]','$1 s0$2e$3'}
    
michaelekins
  • 529
  • 1
  • 7
  • 23