如何在尝试保存文件名之前删除非法字符?

时间:2014-04-14 17:49:24

标签: powershell powershell-v2.0 powershell-v3.0

我能够在PowerShell脚本中找到如何使用GetInvalidFileNameChars()方法。但是,它似乎也过滤掉了空格(这是我不想要的)。

编辑:也许我不是要问这个问题。我希望下面的函数包含文件名中已存在的空格。目前,该脚本会过滤掉空格。

Function Remove-InvalidFileNameChars {

param([Parameter(Mandatory=$true,
    Position=0,
    ValueFromPipeline=$true,
    ValueFromPipelineByPropertyName=$true)]
    [String]$Name
)

return [RegEx]::Replace($Name, "[{0}]" -f ([RegEx]::Escape([String][System.IO.Path]::GetInvalidFileNameChars())), '')}

6 个答案:

答案 0 :(得分:37)

将字符数组转换为System.String实际上似乎是用空格连接数组元素,这意味着

[string][System.IO.Path]::GetInvalidFileNameChars()

相同
[System.IO.Path]::GetInvalidFileNameChars() -join ' '

当你真正想要

[System.IO.Path]::GetInvalidFileNameChars() -join ''

@mjolinor所述(+1),这是由output field separator$OFS)引起的。

证据:

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♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼:\*\?\\/

将您的功能更改为以下内容:

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)
}

它应该做你想要的。

答案 1 :(得分:6)

我怀疑它与非显示字符被强制为[string]进行正则表达式操作(最后表示为空格)。

看看这是否效果不佳:

([char[]]$name | where { [IO.Path]::GetinvalidFileNameChars() -notcontains $_ }) -join ''

这将进行直接字符比较,并且似乎更可靠(嵌入空格不会被删除)。

$name = 'abc*\ def.txt'
([char[]]$name | where { [IO.Path]::GetinvalidFileNameChars() -notcontains $_ }) -join ''

abc def.txt

编辑 - 我相信@Ansgar对于将字符数组转换为字符串所造成的空间是正确的。这个空间由$ OFS引入。

答案 2 :(得分:4)

我想要空格来替换所有非法字符,以便用空格替换空格

$Filename = $ADUser.SamAccountName
[IO.Path]::GetinvalidFileNameChars() | ForEach-Object {$Filename = $Filename.Replace($_," ")}
$Filename = "folder\" + $Filename.trim() + ".txt"

答案 3 :(得分:2)

目前我最喜欢的实现方法是:

$Path.Split([IO.Path]::GetInvalidFileNameChars()) -join '_'

这会用_替换所有无效字符,并且易于阅读。

答案 4 :(得分:1)

请尝试使用相同基础功能的单行程。

匹配

'?Some "" File Name <:.txt' -match ("[{0}]"-f (([System.IO.Path]::GetInvalidFileNameChars()|%{[regex]::Escape($_)}) -join '|'))

替换

'?Some "" File Name <:.txt' -replace ("[{0}]"-f (([System.IO.Path]::GetInvalidFileNameChars()|%{[regex]::Escape($_)}) -join '|')),'_'

答案 5 :(得分:0)

[System.IO.Path]::GetInvalidFileNameChars()返回一组无效字符。如果它为你返回空格字符(它不适合我),你总是可以迭代数组并删除它。

> $chars = @()
> foreach ($c in [System.IO.Path]::GetInvalidFileNameChars())
  {
     if ($c -ne ' ')
     {
        $chars += $c
     }
  }

然后您可以使用$chars,就像使用GetInvalidFileNameChars()的输出一样。