Search code examples
powershellpathescapingpowershell-3.0microsoft-bits

Function to escape characters in paths


Is there a function in PowerShell for escaping characters in paths?

NB: I'm aware that most cmdlets which provide a Path parameter also provide a LiteralPath parameter which resolves this issue. This question is more from curiosity than need, as in most use cases I can think of, switching to LiteralPath makes sense. However there are some genuine use-cases (e.g. Start-BitsTransfer has a Source parameter, but no literal equivalent).

Detail

If I have a file c:\temp\test[0123].txt, instead of Get-Item 'c:\temp\test[0123].txt', I'd have to use Get-Item 'c:\temp\test`[0123`].txt' to get a result (or make use of the LiteralPath parameter).

Even the path returned by another PowerShell command returns an unescaped string; i.e. Get-ChildItem 'c:\temp\' -Filter 'test*.txt' | Convert-Path | Get-Item fails (NB: if we pass the actual FileSystemInfo object all works, but that object has no properties with the correctly escaped string path).

We can easily escape this using code such as below:

$path = 'c:\temp\test[0123].txt'
$path = $path -replace '([][[])', '`$1' # escape square brackets by adding back ticks
Get-Item $path

However when escaping strings, standard advice is to avoid rolling your own solution / to make use of the language's solutions to these issues.

Is there any pre-existing function in PowerShell for this purpose, or any recommended way of approaching this; or is the only option to use a bespoke function (e.g. below)?

function ConvertFrom-LiteralPath {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]$LiteralPath
    )
    process {
        (New-Object -TypeName 'PSObject' -Property @{
            LiteralPath = $LiteralPath
            Path = $LiteralPath -replace '([][[\*\?])', '`$1' # escapes ], [, *, and ?
        })
    }
}

Info on special characters:


Solution

  • There is the following method you can use:

    [Management.Automation.WildcardPattern]::Escape('test[1].txt')
    

    Returns:

    test`[1`].txt
    

    Documented here:
    https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.wildcardpattern.escape