1

Windowsファイルシステム(ネットワークのOS Xクライアントによってそこに置かれた)上の不正なファイル名をクリーンアップする関数を作成/変更しようとしています。スクリプトは正常に動作しますが、正規表現で特定のメタ文字を渡そうとすると、-AllMatches で実行されるチェックは、肯定的な一致に対して false を返します (テストのために意図的に違法な名前のフォルダーを使用します)。文字が (提供されたループを使用せずに) 個別に処理された場合、それらは true を返します。私はすべてのエスケープ方法 (および \ と ` の 2 つの組み合わせ) を試しましたが、うまくいきませんでした。その他の特殊文字 (& など) は正常に機能します。

なぜこのように動作するのか、誰にも考えがありますか? (注: 以下でコメント化されている不正な文字の 2 つの宣言は、機能しない文字と機能する文字に分けられます。

function Check-IllegalCharacters ($Path, [switch]$Fix, [switch]$Verbose)
{
Write-Host Checking files in $Path, please wait...
#Get all files and folders under the path specified
$items = Get-ChildItem -Path $Path -Recurse
foreach ($item in $items)
{
    #Check if the item is a file or a folder
    if ($item.PSIsContainer) { $type = "Folder" }
    else { $type = "File" }

    #Report item has been found if verbose mode is selected
    if ($Verbose) { Write-Host Found a $type called $item.FullName }

    #Check if item name is 128 characters or more in length
    if ($item.Name.Length -gt 127)
    {
        Write-Host $type $item.Name is 128 characters or over and will need to be truncated -ForegroundColor Red
    }
    else
    {
    #$illegalChars = '[<>?*|/\:"]'    $illegalChars = '[&{}~#%]'
        #Got this from http://powershell.com/cs/blogs/tips/archive/2011/05/20/finding-multiple-regex-matches.aspx
        $illegalChars = '[&{}~#%]'
        filter Matches($illegalChars)
        {
            $item.Name | Select-String -AllMatches $illegalChars |
            Select-Object -ExpandProperty Matches
            Select-Object -ExpandProperty Values

        }

        #Replace illegal characters with legal characters where found
        $newFileName = $item.Name
        Matches $illegalChars | ForEach-Object {
            Write-Host $type $item.FullName has the illegal character $_.Value -ForegroundColor Red
            #These characters may be used on the file system but not SharePoint
            if ($_.Value -match "&") { $newFileName = ($newFileName -replace "&", "and") }
            if ($_.Value -match "{") { $newFileName = ($newFileName -replace "{", "(") }
            if ($_.Value -match "}") { $newFileName = ($newFileName -replace "}", ")") }
            if ($_.Value -match "~") { $newFileName = ($newFileName -replace "~", "-") }
            if ($_.Value -match "#") { $newFileName = ($newFileName -replace "#", "") }
            if ($_.Value -match "%") { $newFileName = ($newFileName -replace "%", "") }
        }

        #Check for start, end and double periods
        if ($newFileName.StartsWith(".")) { Write-Host $type $item.FullName starts with a period -ForegroundColor red }
        while ($newFileName.StartsWith(".")) { $newFileName = $newFileName.TrimStart(".") }
        if ($newFileName.EndsWith(".")) { Write-Host $type $item.FullName ends with a period -ForegroundColor Red }
        while ($newFileName.EndsWith("."))   { $newFileName = $newFileName.TrimEnd(".") }
        if ($newFileName.Contains("..")) { Write-Host $type $item.FullName contains double periods -ForegroundColor red }
        while ($newFileName.Contains(".."))  { $newFileName = $newFileName.Replace("..", ".") }

        #Fix file and folder names if found and the Fix switch is specified
        if (($newFileName -ne $item.Name) -and ($Fix))
        {
            Rename-Item $item.FullName -NewName ($newFileName)
            Write-Host $type $item.Name has been changed to $newFileName -ForegroundColor Blue
        }
    }
}
}

誰かが助けてくれたらどうもありがとう!

編集:さらに明確にするために、ここの関数はそのままで正常に機能します。それは、正規表現を他のバリアント $illegalChars = '[<>?*|/\:"]' に変更する (および必要に応じてエスケープする) 場合のみです。正常に動作し、エラーは発生しませんが、これらの文字が含まれるファイルやフォルダーは検出されません。

関数をロードしてから、'Check-IllegalCharacters -Path $path -Verbose' を実行して実行できます。

4

1 に答える 1

0

以下の例でわかるように、文字が Regex メタ文字の場合、置換演算子の左側に「\」を使用する必要があります。switch-regexオプションが役立ちます。

clear-host
$stringTotest = "coucou & Bonjour {vous} [<>?*|/\:`"]"

switch -regex ($stringTotest)
{
    "&"
  {
        $stringTotest = $stringTotest -replace '&', 'et'
    }
    "{"
  {
        $stringTotest = $stringTotest -replace '{', '('
    }
    "{"
  {
        $stringTotest = $stringTotest -replace '}', ')'
    }
    "\["
  {
        $stringTotest = $stringTotest -replace '\[', '1'
    }
    "<"
  {
        $stringTotest = $stringTotest -replace '<', '2'
    }
    ">"
  {
        $stringTotest = $stringTotest -replace '>', '3'
    }
    "\?"
  {
        $stringTotest = $stringTotest -replace '\?', '4'
    } 
    "\*"
  {
        $stringTotest = $stringTotest -replace '\*', '5'
    }
    "\|"
  {
        $stringTotest = $stringTotest -replace '\|', '6'
    }
    "/"
  {
        $stringTotest = $stringTotest -replace '/', '7'
    }  
    "\\"
  {
        $stringTotest = $stringTotest -replace '\\', '8'
    }    
    ":"
  {
        $stringTotest = $stringTotest -replace ':', '9'
    }      
    "`""
  {
        $stringTotest = $stringTotest -replace '"', '0'
    }    
    "\]"
  {
        $stringTotest = $stringTotest -replace '\]', '1'
    }    
    default
  {
        break
    }
}

$stringTotest
于 2012-05-18T07:29:22.243 に答える