Как удалить недопустимые символы перед попыткой сохранить имена файлов?
Мне удалось найти способ использования метода GetInvalidFileNameChars()
в PowerShell script. Однако, похоже, он также отфильтровывает пробелы (чего я не хочу).
EDIT: Возможно, я не прошу об этом достаточно ясно. Я хочу, чтобы функция ниже включала пробелы, которые уже существуют в именах файлов. В настоящее время script отфильтровывает пробелы.
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())), '')}
Ответы
Ответ 1
Приведение символьного массива в System.String
фактически похоже на элементы массива с пробелами, что означает, что
[string][System.IO.Path]::GetInvalidFileNameChars()
делает то же самое, что и
[System.IO.Path]::GetInvalidFileNameChars() -join ' '
когда вы действительно хотите
[System.IO.Path]::GetInvalidFileNameChars() -join ''
Как @mjolinor упоминается (+1), это вызвано разделителем выходных полей ($OFS
).
Доказательства:
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♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼:\*\?\\/
Измените свою функцию примерно так:
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)
}
и он должен делать то, что вы хотите.
Ответ 2
Я подозреваю, что это связано с тем, что символы, не отображаемые, принуждаются к [string] для операции регулярного выражения (и заканчиваются выражением как пробелы).
Посмотрите, не работает ли это лучше:
([char[]]$name | where { [IO.Path]::GetinvalidFileNameChars() -notcontains $_ }) -join ''
Это сделает прямое сравнение char и, кажется, более надежным (встроенные пространства не удаляются).
$name = 'abc*\ def.txt'
([char[]]$name | where { [IO.Path]::GetinvalidFileNameChars() -notcontains $_ }) -join ''
abc def.txt
Изменить - я считаю, что @Ansgar правильно относится к пространству, вызванному литьем массива символов в строку. Пространство вводится через $OFS.
Ответ 3
Мне нужны пробелы для замены всех недопустимых символов, поэтому пространство заменяется пробелом
$Filename = $ADUser.SamAccountName
[IO.Path]::GetinvalidFileNameChars() | ForEach-Object {$Filename = $Filename.Replace($_," ")}
$Filename = "folder\" + $Filename.trim() + ".txt"
Ответ 4
[System.IO.Path]::GetInvalidFileNameChars()
возвращает массив недопустимых символов. Если он возвращает символ пробела для вас (что он не делает для меня), вы всегда можете перебирать массив и удалять его.
> $chars = @()
> foreach ($c in [System.IO.Path]::GetInvalidFileNameChars())
{
if ($c -ne ' ')
{
$chars += $c
}
}
Затем вы можете использовать $chars
, поскольку вы использовали бы выход из GetInvalidFileNameChars()
.
Ответ 5
Попробуйте этот однострочный вкладыш с той же базовой функцией.
для соответствия
'?Some "" File Name <:.txt' -match ("[{0}]"-f (([System.IO.Path]::GetInvalidFileNameChars()|%{[regex]::Escape($_)}) -join '|'))