Vicky Dev
Vicky Dev

Reputation: 2173

Powershell Rename dynamic filenames containing square brackets, from the filetype scans in the directory

I don't much know(in details and specifics) about Powershell's silly and ridiculous issues/bugs in handling square brackets(just because it escapes strings multiple times internally) in the path strings, where I have to use Regex with asterisk(*) to match/catch the patterns.

I did heavy Googling and found that there's method [WildcardPattern]::Escape($Filename) that could help me Rename-Item such dynamic file paths, I thought the below code would work with such dynamic paths which are result of file-type scans in the current folder, but disappointingly, it doesn't:

Set-Location "$PSScriptRoot"
$MkvFiles = Get-ChildItem -Filter *.mkv -Path $Path
Foreach ($MkvFile in $MkvFiles) {
    $MkvOrigName = [WildcardPattern]::Escape($MkvFile.Name)
    $MkvOrigFullname = [WildcardPattern]::Escape($MkvFile.FullName)
    If ($MkvOrigName -Match '.*(S[0-9]{2}E[0-9]{2}).*') {
        $NewNameNoExt = $MkvOrigFullname -Replace '.*(S[0-9]{2}E[0-9]{2}).*', '$1'
        $NewName = "$NewNameNoExt.mkv"
        Rename-Item $MkvOrigFullname -NewName $NewName
    }
}

I am getting the following error with Rename-Item command when I run the above script on the folder that contains the files such as given at the end of question:

Rename-Item : An object at the specified path C:\Users\Username\Downloads\WebseriesName Season 
4\WebSeriesName.2016.S04E13.iNTERNAL.480p.x264-mSD`[eztv`].mkv does not exist.
At C:\Users\Username\Downloads\WebseriesName Season 4\BulkFileRenamerFinalv1.ps1:12 char:9
+         Rename-Item $MkvOrigFullname -NewName $NewName
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The Webseries file paths in the current folder, that I am dealing with are like these:

WebSeriesName.2016.S04E01.HDTV.x264-SVA[eztv].mkv
WebSeriesName.2016.S04E02.HDTV.x264-SVA[eztv].mkv
....
....
WebSeriesName.2016.S04E12.iNTERNAL.480p.x264-mSD[eztv].mkv
WebSeriesName.2016.S04E13.iNTERNAL.480p.x264-mSD[eztv].mkv

Someone could help me figuring out this problem generically without need to headbang with what the filenames strings contain, as long as they contain the string like S04E01,S04E02 etc. and surely contain square brackets ? That is, how can I escape the square brackets and rename them, as apparent in the code afore-mentioned, to the names given below ?

S04E01.mkv
S04E02.mkv
....
....
S04E12.mkv
S04E13.mkv

Upvotes: 0

Views: 849

Answers (1)

AdminOfThings
AdminOfThings

Reputation: 25001

If you use the pipeline, you don't need to worry about escaping paths. This is because PSPath property will automatically bind to the -LiteralPath parameter on Rename-Item.

Set-Location "$PSScriptRoot"
$MkvFiles = Get-ChildItem -Filter *.mkv -Path $Path
Foreach ($MkvFile in $MkvFiles) {
    If ($MkvFile.Name -Match '.*(S[0-9]{2}E[0-9]{2}).*') {
        $MkvFile | Rename-Item -NewName {"{0}{1}" -f $matches.1,$_.Extension}
    }
}

Explanation:

The -NewName parameter supports delay-bind scripting. So we can use a script block to do the property/string manipulation.

If wildcards are not needed for the path query, then using -LiteralPath is the best approach. The -LiteralPath value is bound exactly as typed (literal/verbatim string). -Path for Get-ChildItem accepts wildcards, but -Path for Rename-Item does not support wildcards. Yet it seems like PowerShell still cares when parsing the command. If you must escape some wildcard characters in a -Path parameter that accepts wildcards, then double quoted paths require 4 backticks and single quoted paths require 2 backticks. This is because two levels of escape are required.

When using -match against a single string even if in a conditional statement, the $matches automatic variable is updated when a match is successful. Capture group matches are accessed using syntax $matches.capturegroupname or $matches[capturegroupname]. Since you did not name the capture group, it was automatically named 1 by the system. A second set of () around a capturing group, would have been 2. It is important to remember that when -match is False, $matches is not updated from its previous value.


Examples of handling wildcard characters in -Path parameters that support wildcards:

# Using double quotes in the path
$Path = "WebSeriesName.2016.S04E01.HDTV.x264-SVA````[eztv].mkv"
Get-ChildItem -Path $Path

# Using single quotes in the path
$Path = "WebSeriesName.2016.S04E01.HDTV.x264-SVA``[eztv].mkv"
Get-ChildItem -Path $Path

# Using LiteralPath
$Path = "WebSeriesName.2016.S04E01.HDTV.x264-SVA[eztv].mkv"
Get-ChildItem -LiteralPath $Path
Rename-Item -LiteralPath $Path -NewName 'MyNewName.mkv'

# Using WildcardPattern Escape method
$Path = 'WebSeriesName.2016.S04E01.HDTV.x264-SVA[eztv].mkv'
$EscapedPath = ([WildcardPattern]::Escape([WildcardPattern]::escape($path)))
Get-ChildItem -Path $EscapedPath

Upvotes: 1

Related Questions