web-dev-qa-db-de.com

Wie entferne ich unzulässige Zeichen, bevor ich versuche, Dateinamen zu speichern?

Ich konnte herausfinden, wie die GetInvalidFileNameChars()-Methode in einem PowerShell-Skript verwendet wird. Es scheint jedoch auch Whitespace herauszufiltern (was ich NICHT will).

EDIT: Vielleicht frage ich das nicht klar genug. Ich möchte, dass die folgende Funktion die bereits in Dateinamen vorhandenen Leerzeichen einschließt. Derzeit filtert das Skript Leerzeichen heraus.

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())), '')}
16
MKANET

Das Casting des Zeichen-Arrays in System.String scheint die Array-Elemente tatsächlich mit Leerzeichen zu verknüpfen

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

macht das gleiche wie

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

wenn du eigentlich willst

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

Wie in @mjolinor (+1) erwähnt, wird dies durch das Ausgabefeld-Trennzeichen ($OFS) verursacht.

Beweis:

PS C: \> [RegEx] :: Escape ([Zeichenfolge] [IO.Path] :: GetInvalidFileNameChars ())
 "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ [RegEx] :: Escape (([IO.Path] :: GetInvalidFileNameChars () -join ''))
 "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ [RegEx] :: Escape (([IO.Path] :: GetInvalidFileNameChars () -join ''))
 "\ | ☺☻ ♥ ♦\t\n♂\f\r ♫►◄↕‼ ¶§▬↨ ↑ ↓ → ← ∟ ▲ ▼:\* \?\\// 
 PS C: \> $ OFS = ''
 PS C: \> [RegEx] :: Escape ([Zeichenfolge] [IO.Path] :: GetInvalidFileNameChars ())
 "\ | ☺☻ ♥ ♦\t\n♂\f\r \\\\\\\\\\\\\\\\\\\\\\\\\\\\\

Ändern Sie Ihre Funktion in etwa wie folgt:

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

und es sollte tun, was Sie wollen.

33
Ansgar Wiechers

Ich vermute, es hat damit zu tun, dass Zeichen, die nicht angezeigt werden, für die Regex-Operation zu [string] gezwungen werden (und am Ende als Leerzeichen ausgedrückt werden).

Sehen Sie, ob dies nicht besser funktioniert:

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

Dies führt zu einem direkten Zeichenvergleich und scheint zuverlässiger zu sein (eingebettete Leerzeichen werden nicht entfernt).

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

abc def.txt

Bearbeiten - Ich glaube, @Ansgar stimmt mit dem Speicherplatz überein, der durch das Umwandeln des Zeichen-Arrays in eine Zeichenfolge verursacht wird. Der Raum wird von $ OFS eingeführt.

6
mjolinor

Ich wollte Leerzeichen, um alle illegalen Zeichen zu ersetzen, damit Leerzeichen durch Leerzeichen ersetzt werden

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

Bitte probieren Sie diesen One-Liner mit der gleichen zugrunde liegenden Funktion. 

passen

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

ersetzen

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

1
user8569534

Mein aktueller Lieblingsweg, dies zu erreichen, ist:

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

Dies ersetzt alle ungültigen Zeichen durch _ und ist sehr gut lesbar.

1
hsimah

[System.IO.Path]::GetInvalidFileNameChars() gibt ein Array ungültiger Zeichen zurück. Wenn das Leerzeichen für Sie zurückgegeben wird (was für mich nicht der Fall ist), können Sie das Array immer wiederholen und es entfernen.

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

Dann können Sie $chars so verwenden, wie Sie die Ausgabe von GetInvalidFileNameChars() verwendet hätten.

0
djs