1

我正在尝试编写/修改一个函数来清除 Windows 文件系统上的非法文件名(由我们网络的 OS X 客户端放置在那里)。该脚本工作得很好,但是当尝试在正则表达式中传递某些元字符时,在 -AllMatches 中执行的检查对于正匹配返回 false(使用故意非法命名的文件夹进行测试)。如果字符是单独完成的(不使用提供的循环),它们返回 true。我已经尝试了所有转义方法(以及两者的组合,\ 和`),但没有运气。其他特殊字符也可以正常工作(例如 &)。

有人对它为什么会这样有任何想法吗?(注意:下面注释掉的两个非法字符声明被分解为不起作用的字符和起作用的字符。

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选项可以帮助您。

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 回答