Одна вещь мы опасающийся - то, что все файлы журнала существуют и могут быть записаны в. Configtest не ловит проблемы с созданием или записью в файлы журнала, так, чтобы мог предотвратить Ваш сервер, перезапускающий правильно, и корректные перезапуски, кажется, не предотвращают это.
Вот что я придумал:
function Get-ActualFileName($file) {
$parent = Split-Path $file
$leaf = Split-Path -Leaf $file
$result = Get-ChildItem $parent | where { $_ -like $leaf }
$result.Name
}
Основная часть файловой системы работает в PowerShell выполняется некоторыми классами .NET в пространстве имен System.IO. Если вы знаете путь (например, в вашем примере вы перешли в то место файловой системы, где находится ваш предметный файл), вы можете использовать что-то вроде
(get-item $pwd).GetFiles('readme.txt')
Поскольку базовые классы .NET чувствительны к регистру, результирующий вывод имен ваших файлов также будет чувствителен к регистру.
Для справки, в примере вы вызываете метод GetFiles объекта System.IO.DirectoryInfo, который представляет текущий рабочий каталог ($ pwd). Вы можете изменить это так, чтобы указывать на каталог, содержащий файл, в котором вам нужно подтвердить регистр.
Все свойства Name, BaseName и FullName должны отражать правильный регистр.
]Самый быстрый способ, который я могу придумать, - это заменить все косые черты на * \ и затем вызвать Get-Item, а чтобы убедиться, что вы не получаете дубликатов, выберите тот, который без учета регистра равен на тот, который вы указали.
$Path = Get-Item "$($Path.TrimEnd('\/') -replace "(?<!:)(\\|/)", '*$1')*" |
Where { $_.FullName -ieq $Path } | Convert-Path
Вместо того, чтобы указывать точное имя, просто используйте подстановочный знак:
PS> Get-Item ReadMe.tx?
это должно вернуть README .TXT
Вот мой быстрый и грязный (без проверки ) подход:
Function Resolve-PathName { [CmdletBinding()]
Param(
[Parameter(ValueFromPipelinebyPropertyName,ValueFromPipeline,Mandatory)]
[Alias("Fullname")]
[string] $File,
[switch] $Cygpath
) Process {
$cur = $File
$stack = New-Object System.Collections.Stack
while ( $cur.length -gt 0) {
$stack.Push( (split-path $cur -Leaf) )
$cur = split-path $cur
}
$cur = get-item ($stack.pop())
while ( $stack.Count -gt 0) {
$cur = $cur | Get-ChildItem -Filter ($stack.Pop())
}
if ($Cygpath) {
cygpath $cur.Fullname
} else {
$cur.Fullname
}
}}
Следующая функция PowerShell основана на элегантном решении другого разработчика для C # по адресу https://stackoverflow.com/a/11436327/854680 .
Потому что ] Get-ChildItem не используется, он намного быстрее , что имеет значение при вызове этой функции десятки или сотни раз.
function Get-FileNameTrueCase {
Param (
[parameter(Mandatory=$true)]
[string]
$DirOrFile
)
if (-not ( (Test-Path $DirOrFile -PathType Leaf) -or (Test-Path $DirOrFile -PathType Container) ) ) {
# File or directory not found
return $DirOrFile
}
$TruePath = "";
foreach ($PathPart in $DirOrFile.Split("\")) {
if ($TruePath -eq "") {
$TruePath = $PathPart.ToUpper() + "\";
continue;
}
$TruePath = [System.IO.Directory]::GetFileSystemEntries($TruePath, $PathPart)[0];
}
return $TruePath;
}
Ответ разобью на две части. 1) Если вас интересует только регистр имени файла и 2) Если вам важен регистр полного пути к файлу.
1. Регистр имени файла
Самый простой способ заставить Powershell выдавать вам правильный регистр имени файла — это выполнить поиск по имени файла. Мы можем добиться этого, используя класс символов RegEx (набор допустимых символов) для первой буквы имени файла.
Для поиска ReadMe.txt можно использовать [R]eadMe.txt. Класс символов RegEx обычно используется для нескольких возможных символов, но в этом случае мы просто используем один, чтобы всегда получать одно совпадение:
Get-Item [R]eadMe.txt | Select Name
Приведенное выше возвращает имя файла с правильным регистром:
README.TXT
Если имя файла предоставляется динамически или просматривается, вы можете использовать следующий простой оператор RegEx, чтобы окружить первые символы скобками:
"ReadMe.txt" -replace "^(.)", '[$1]'
Это возвращает:
[R]eadMe.txt
Пример использования для получения имени файла с правильным регистром:
$filename = "ReadMe.txt"
Get-Item ($filename -replace "^(.)", '[$1]') | Select Name
Приведенный выше пример возвращает имя файла с правильным регистром:
README.TXT
2. Полный путь к файлу
Основная концепция здесь остается той же, что и в первой части.У нас будет Powershell, который даст нам правильный регистр всех сегментов полного пути к файлу, заставив его искать каждый сегмент.
Как и в нашем предыдущем подходе, самый простой способ сделать это — заключить первый символ каждого сегмента в квадратные скобки.
Если имя файла известно, например:
c:\WINDOWS\systeM32\driverS\ETC\hosTS
Вы можете получить правильный регистр для полного пути, введя класс символов RegEx (набор допустимых символов) для первой буквы каждого сегмента:
Get-Item c:\[W]INDOWS\[s]ysteM32\[d]riverS\[E]TC\[h]osTS | Select FullName
Это в моей системе возвращает полный путь и имя файла с правильным регистром:
C:\Windows\System32\drivers\etc\hosts
Если полный путь к файлу динамически передается или просматривается, вы можете просто использовать следующий оператор RegEx для автоматического заключения первого символа каждого сегмента в квадратные скобки:
$FullFilePath = "c:\WINDOWS\systeM32\driverS\ETC\hosts"
$FullFilePath -replace "(\\|/)(.)", '$1[$2]'
Это возвращает:
c:\[W]INDOWS\[s]ysteM32\[d]riverS\[E]TC\[h]osts
Пример использования для получения полного пути к файлу с правильным регистром:
$FullFilePath = "c:\WINDOWS\systeM32\driverS\ETC\hosts"
Get-Item ($FullFilePath -replace "(\\|/)(.)", '$1[$2]') | Select FullName
Приведенное выше возвращает полный путь к файлу с правильным регистром case:
C:\Windows\System32\drivers\etc\hosts