How to strip illegal characters before trying to save filenames?
Casting the character array to System.String
actually seems to join the array elements with spaces, meaning that
[string][System.IO.Path]::GetInvalidFileNameChars()
does the same as
[System.IO.Path]::GetInvalidFileNameChars() -join ' '
when you actually want
[System.IO.Path]::GetInvalidFileNameChars() -join ''
As @mjolinor mentioned (+1), this is caused by the output field separator ($OFS
).
Evidence:
PS C:\> [RegEx]::Escape([string][IO.Path]::GetInvalidFileNameChars()) "\ \ \|\ \ ☺\ ☻\ ♥\ ♦\ ♣\ ♠\ \\ \t\ \n\ ♂\ \f\ \r\ ♫\ ☼\ ►\ ◄\ ↕\ ‼\ ¶\ §\ ▬\ ↨\ ↑\ ↓\ →\ ←\ ∟\ ↔\ ▲\ ▼\ :\ \*\ \?\ \\\ / PS C:\> [RegEx]::Escape(([IO.Path]::GetInvalidFileNameChars() -join ' ')) "\ \ \|\ \ ☺\ ☻\ ♥\ ♦\ ♣\ ♠\ \\ \t\ \n\ ♂\ \f\ \r\ ♫\ ☼\ ►\ ◄\ ↕\ ‼\ ¶\ §\ ▬\ ↨\ ↑\ ↓\ →\ ←\ ∟\ ↔\ ▲\ ▼\ :\ \*\ \?\ \\\ / PS C:\> [RegEx]::Escape(([IO.Path]::GetInvalidFileNameChars() -join '')) "\| ☺☻♥♦\t\n♂\f\r♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼:\*\?\\/ PS C:\> $OFS='' PS C:\> [RegEx]::Escape([string][IO.Path]::GetInvalidFileNameChars()) "\| ☺☻♥♦\t\n♂\f\r♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼:\*\?\\/
Change your function to something like this:
Function Remove-InvalidFileNameChars {
param(
[Parameter(Mandatory=$true,
Position=0,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)]
[String]$Name
)
$invalidChars = [IO.Path]::GetInvalidFileNameChars() -join ''
$re = "[{0}]" -f [RegEx]::Escape($invalidChars)
return ($Name -replace $re)
}
and it should do what you want.
My current favourite way to accomplish this is:
$Path.Split([IO.Path]::GetInvalidFileNameChars()) -join '_'
This replaces all invalid characters with _
and is very human readable, compared to alternatives such as:
$Path -replace "[$([RegEx]::Escape([string][IO.Path]::GetInvalidFileNameChars()))]+","_"