PowerShell 开始在文件路径前添加 Microsoft.PowerShell.Core\FileSystem::
PowerShell starts prepending file paths with Microsoft.PowerShell.Core\FileSystem::
我在 PowerShell 中遇到以下行为,我无法解释并且觉得很麻烦。
我在任意目录工作,目录路径如提示:
PS C:\Users\Rene\AppData\Local\Temp>
此外,get-location
报告 "correct" 路径:
PS C:\Users\Rene\AppData\Local\Temp> get-location
Path
----
C:\Users\Rene\AppData\Local\Temp
然后我输入 mkdir xyz | cd
以创建一个目录并将工作目录更改为这个新目录:
PS C:\Users\Rene\AppData\Local\Temp> mkdir xyz | cd
突然提示中的路径前缀为Microsoft.PowerShell.Core\FileSystem::
:
PS Microsoft.PowerShell.Core\FileSystem::C:\Users\Rene\AppData\Local\Temp\xyz>
此更改也反映在 get-location
:
PS Microsoft.PowerShell.Core\FileSystem::C:\Users\Rene\AppData\Local\Temp\xyz> get-location
Path
----
Microsoft.PowerShell.Core\FileSystem::C:\Users\Rene\AppData\Local\Temp\xyz
这是怎么回事,我怎样才能关闭该前缀?
倒序:
How can I turn that prefix off?
简单,使用显式管道绑定!
mkdir xyz |cd -Path {$_.FullName}
What is going on here?
好问题!您在这里看到的是提供程序 cmdlet(Get-ChildItem
、Get-Item
、Set-Location
等)如何实现 管道绑定的副作用 .
当您针对 FileSystem
提供程序调用 New-Item
(mkdir
所做的)时,它 returns 一个对象(对应于新创建的文件或目录) ) 有一堆隐藏的属性,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
当您在下游使用提供程序 cmdlet(例如 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}
为什么 提供程序 cmdlet 的管道绑定以这种方式实现的真正原因是双重的:
- 将 "provider-native" 字符串表示直接绑定到
Path
可能会产生与 globbing 相关的意外后果
Get-Item -Path 'a[bcd]'
和 Get-Item -LiteralPath 'a[bcd]'
是两个 截然不同的 查询,例如
- 绑定到提供者限定的
PSPath
值意味着我们可以在不丢失自动绑定的情况下将位置切换到不同的提供者:
- 即。
PS Cert:\> $aFile |Get-Content
正常工作
我在 PowerShell 中遇到以下行为,我无法解释并且觉得很麻烦。
我在任意目录工作,目录路径如提示:
PS C:\Users\Rene\AppData\Local\Temp>
此外,get-location
报告 "correct" 路径:
PS C:\Users\Rene\AppData\Local\Temp> get-location
Path
----
C:\Users\Rene\AppData\Local\Temp
然后我输入 mkdir xyz | cd
以创建一个目录并将工作目录更改为这个新目录:
PS C:\Users\Rene\AppData\Local\Temp> mkdir xyz | cd
突然提示中的路径前缀为Microsoft.PowerShell.Core\FileSystem::
:
PS Microsoft.PowerShell.Core\FileSystem::C:\Users\Rene\AppData\Local\Temp\xyz>
此更改也反映在 get-location
:
PS Microsoft.PowerShell.Core\FileSystem::C:\Users\Rene\AppData\Local\Temp\xyz> get-location
Path
----
Microsoft.PowerShell.Core\FileSystem::C:\Users\Rene\AppData\Local\Temp\xyz
这是怎么回事,我怎样才能关闭该前缀?
倒序:
How can I turn that prefix off?
简单,使用显式管道绑定!
mkdir xyz |cd -Path {$_.FullName}
What is going on here?
好问题!您在这里看到的是提供程序 cmdlet(Get-ChildItem
、Get-Item
、Set-Location
等)如何实现 管道绑定的副作用 .
当您针对 FileSystem
提供程序调用 New-Item
(mkdir
所做的)时,它 returns 一个对象(对应于新创建的文件或目录) ) 有一堆隐藏的属性,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
当您在下游使用提供程序 cmdlet(例如 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}
为什么 提供程序 cmdlet 的管道绑定以这种方式实现的真正原因是双重的:
- 将 "provider-native" 字符串表示直接绑定到
Path
可能会产生与 globbing 相关的意外后果Get-Item -Path 'a[bcd]'
和Get-Item -LiteralPath 'a[bcd]'
是两个 截然不同的 查询,例如
- 绑定到提供者限定的
PSPath
值意味着我们可以在不丢失自动绑定的情况下将位置切换到不同的提供者:- 即。
PS Cert:\> $aFile |Get-Content
正常工作
- 即。