2014-04-14 15 views
12

Udało mi się znaleźć sposób użycia metody GetInvalidFileNameChars() w skrypcie PowerShell. Wydaje się jednak, że odfiltrowuje również białe spacje (czego NIE chcę).Jak usunąć niedozwolone znaki przed próbą zapisania nazw plików?

EDYCJA: Może nie wymagam tego wystarczająco jasno. Chcę, aby poniżej funkcja ZAWIERA obszary, które już istnieją w nazwach plików. Obecnie skrypt odfiltrowuje spacje.

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

Odpowiedz

26

Casting tablica znaków do System.String rzeczywiście wydaje się, aby dołączyć do elementów tablicy ze spacjami, co oznacza, że ​​

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

działa tak samo jak

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

kiedy rzeczywiście chcesz

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

Jak wspomniano @mjolinor (+1), jest to spowodowane przez output field separator ($OFS).

Dowody:

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

Zmień swoją funkcję do czegoś takiego:

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

i powinien robić to, co chcesz.

+0

Dziękuję bardzo za wyjaśnienie i wysłanie działającego rozwiązania! – MKANET

5

Podejrzewam, że ma do czynienia ze znaków spoza wyświetlacz jest zmuszany do [ciąg znaków] dla funkcjonowania regex (a kończąc wyrażona jako spacjami).

Zobacz, czy to nie działa lepiej:

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

które zrobi prostą porównanie char, i wydaje się być bardziej wiarygodne (spacje nie są usuwane).

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

abc def.txt 

Edytuj - Uważam, że @Ansgar ma poprawne miejsce, które powstało w wyniku rzucania tablicy znaków do łańcucha. Przestrzeń jest wprowadzana przez $ OFS.

+0

doskonałe rozwiązanie Rob. –

0

[System.IO.Path]::GetInvalidFileNameChars() zwraca tablicę nieprawidłowych znaków. Jeśli zwraca nam znak spacji (czego nie robi dla mnie), zawsze możesz iterować po tablicy i ją usunąć.

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

Następnie można użyć $chars jak byś stosowane wyjście z GetInvalidFileNameChars().

2

Chciałem spacji aby wymienić wszystkie niedozwolone znaki więc przestrzeń otrzymuje z przestrzeni

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

Łatwy i czysty! – tbolender

0

Spróbuj tego jednego-liner z tej samej funkcji podstawowej.

dopasować

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

zastąpić

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

Powiązane problemy