我正在尝试编写/修改一个函数来清理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 ='[&lt;&gt;?* | / \: “]'它不再正常运行。它会运行得很好,没有错误,但它不会捕获任何带有这些字符的文件或文件夹。
可以加载该函数,然后执行'Check-IllegalCharacters -Path $ path -Verbose'
答案 0 :(得分:0)
正如您在下面的示例中所看到的,当caracter是Regex元字符时,您必须在替换运算符的左侧使用'\'。切换-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