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



我能够找到如何在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())), '')}

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

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

和一样

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

当你真正想要时

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

正如@mjolinor提到的(+1),这是由输出字段分隔符($OFS)引起的。

证据:

PS C:\>[RegEx]::转义([string][IO.Path]::GetInvalidFileNameChars())"☺\☻\♥\ ♦\ ♣\ ♠\ \\ \t\\n\♂\ \f\\r\♫\ ☼\ ►\ ◄\↕\ ‼\¶\§\▬\ ↨\ ↑\ ↓\ →\ ←\ ∟\↔\▲\ ▼\ :\ \*\ \?\ \\\/PS C:\>[RegEx]::转义(([IO.Path]::GetInvalidFileNameChars()-加入")"☺\☻\♥\ ♦\ ♣\ ♠\ \\ \t\\n\♂\ \f\\r\♫\ ☼\ ►\ ◄\↕\ ‼\¶\§\▬\ ↨\ ↑\ ↓\ →\ ←\ ∟\↔\▲\ ▼\ :\ \*\ \?\ \\\/PS C:\>[RegEx]::转义(([IO.Path]::GetInvalidFileNameChars()-加入")"☺☻♥♦\t\n♂\f\r♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼:\*\?\\/PS C:\>$OFS=''PS C:\>[RegEx]::转义([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)
}

它应该做你想做的事。

我目前最喜欢的方法是:

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

这将用_替换所有无效字符,与等替代方案相比,它非常便于人类阅读

$Path -replace "[$([RegEx]::Escape([string][IO.Path]::GetInvalidFileNameChars()))]+","_"

我怀疑这与regex操作中非显示字符被强制为[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引入。

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

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

请尝试使用相同底层函数的这一行。

以匹配

'?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 '|')),'_'

[System.IO.Path]::GetInvalidFileNameChars()返回一个无效字符数组。如果它为您返回空格字符(我没有这样做),您可以始终迭代数组并将其删除。

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

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

非常不同的、组合的、灵活的方法。我发现GetInvalidFileNameChars()并没有获得所有符合我需要的非法字符。

$arrInvalidChars = '[]/|+={}-$%^&*()'.ToCharArray()
$cleanName = 'a[]|+={9}-$%^&*()b'
$arrInvalidChars | % { $cleanName = $cleanName.replace($_,'_')}

返回$cleanName='a_______ 9__________ b'

最新更新