В обратном порядке:
Как отключить этот префикс?
Легко, используйте явное конвейерное связывание!
mkdir xyz |cd -Path {$_.FullName}
Что здесь происходит?
Отличный вопрос! Здесь вы видите побочный эффект от того, как командлеты провайдера (Get-ChildItem
, Get-Item
, Set-Location
et c.) Реализуют конвейерную привязку .
Когда вы вызываете New-Item
(что делает mkdir
) для поставщика FileSystem
, он возвращает объект (соответствующий вновь созданному файлу или каталогу), который имеет набор скрытых свойств, которые использует PowerShell. отслеживать элементы у разных поставщиков - их можно обнаружить с помощью Get-Member -Force
:
PS C:\> Get-Item .|Get-Member PS* -MemberType NoteProperty -Force
TypeName: System.IO.DirectoryInfo
Name MemberType Definition
---- ---------- ----------
PSChildName NoteProperty string PSChildName=C:\
PSDrive NoteProperty PSDriveInfo PSDrive=C
PSIsContainer NoteProperty bool PSIsContainer=True
PSParentPath NoteProperty string PSParentPath=
PSPath NoteProperty string PSPath=Microsoft.PowerShell.Core\FileSystem::C:\
PSProvider NoteProperty ProviderInfo PSProvider=Microsoft.PowerShell.Core\FileSystem
Когда вы создаете оператор конвейера с помощью командлета поставщика (например, Set-Location
/ cd
) в нисходящем направлении , он использует значение PSPath
, определенное поставщиком, чтобы связать входной объект.
Это можно наблюдать с помощью Trace-Command
:
PS C:\> Trace-Command -Expression {Get-Item .|Set-Location} -Name ParameterBinding,MemberResolution -PSHost
Что приводит к (я удалил детали для Get-Item
для краткости):
DEBUG: ParameterBinding Information: 0 : BIND NAMED cmd line args [Set-Location]
DEBUG: ParameterBinding Information: 0 : BIND POSITIONAL cmd line args [Set-Location]
DEBUG: ParameterBinding Information: 0 : BIND cmd line args to DYNAMIC parameters.
DEBUG: ParameterBinding Information: 0 : MANDATORY PARAMETER CHECK on cmdlet [Set-Location]
DEBUG: ParameterBinding Information: 0 : CALLING BeginProcessing
DEBUG: ParameterBinding Information: 0 : CALLING BeginProcessing
DEBUG: ParameterBinding Information: 0 : BIND PIPELINE object to parameters: [Set-Location]
DEBUG: ParameterBinding Information: 0 : PIPELINE object TYPE = [System.IO.DirectoryInfo]
DEBUG: ParameterBinding Information: 0 : RESTORING pipeline parameter's original values
DEBUG: ParameterBinding Information: 0 : Parameter [Path] PIPELINE INPUT ValueFromPipeline NO COERCION
DEBUG: ParameterBinding Information: 0 : BIND arg [C:\\] to parameter [Path]
DEBUG: ParameterBinding Information: 0 : BIND arg [C:\\] to param [Path] SKIPPED
DEBUG: ParameterBinding Information: 0 : Parameter [Path] PIPELINE INPUT ValueFromPipelineByPropertyName NO COERCION
DEBUG: MemberResolution Information: 0 : Lookup
DEBUG: MemberResolution Information: 0 : "Path" NOT present in type table.
DEBUG: MemberResolution Information: 0 : Adapted member: not found.
DEBUG: ParameterBinding Information: 0 : Parameter [StackName] PIPELINE INPUT ValueFromPipelineByPropertyName NO COERCION
DEBUG: MemberResolution Information: 0 : Lookup
DEBUG: MemberResolution Information: 0 : "StackName" NOT present in type table.
DEBUG: MemberResolution Information: 0 : Adapted member: not found.
DEBUG: ParameterBinding Information: 0 : Parameter [LiteralPath] PIPELINE INPUT ValueFromPipelineByPropertyName NO COERCION
DEBUG: MemberResolution Information: 0 : Lookup
DEBUG: MemberResolution Information: 0 : "LiteralPath" NOT present in type table.
DEBUG: MemberResolution Information: 0 : Adapted member: not found.
DEBUG: MemberResolution Information: 0 : Lookup
DEBUG: MemberResolution Information: 0 : Found PSObject instance member: PSPath.
DEBUG: ParameterBinding Information: 0 : BIND arg [Microsoft.PowerShell.Core\FileSystem::C:\] to parameter [LiteralPath]
DEBUG: ParameterBinding Information: 0 : BIND arg [Microsoft.PowerShell.Core\FileSystem::C:\] to param [LiteralPath] SUCCESSFUL
DEBUG: ParameterBinding Information: 0 : MANDATORY PARAMETER CHECK on cmdlet [Set-Location]
DEBUG: ParameterBinding Information: 0 : CALLING EndProcessing
DEBUG: ParameterBinding Information: 0 : CALLING EndProcessing
Как видите, PowerShell отказывается от привязки C:\
к Set-Location
s -Path
параметру, так как каким-то образом более подходящим является привязка значения свойства PSPath
к -LiteralPath
?!
Причина этого является то, что параметр -LiteralPath
имеет псевдоним PSPath
, что можно увидеть, покопав бит с помощью Get-Command
:
PS C:\> (Get-Command Set-Location).Parameters['LiteralPath'] |Select Aliases
Aliases
-------
{PSPath}
Реальная причина почему конвейерные привязки для провайдера Командлеты реализованы следующим образом:
- Привязка "нативного" представления строки поставщика напрямую к
Path
может иметь непредвиденные последствия, связанные с globbing Get-Item -Path 'a[bcd]'
и Get-Item -LiteralPath 'a[bcd]'
- это два дико разных запроса, например
- Привязка к значению
PSPath
, определенному поставщиком, означает, что мы можем переключить местоположение в другой провайдер без потери автоматов c привязка: - ie.
PS Cert:\> $aFile |Get-Content
просто работает