Ren*_*ger 3 filesystems powershell
我在 PowerShell 中遇到以下行为,我无法解释并且觉得很麻烦。
我正在任意目录中工作,目录的路径显示在提示中:
PS C:\Users\Rene\AppData\Local\Temp>
Run Code Online (Sandbox Code Playgroud)
另外,get-location报告“正确”路径:
PS C:\Users\Rene\AppData\Local\Temp> get-location
Path
----
C:\Users\Rene\AppData\Local\Temp
Run Code Online (Sandbox Code Playgroud)
然后,我键入命令mkdir xyz | cd以创建一个目录并将工作目录更改为这个新目录:
PS C:\Users\Rene\AppData\Local\Temp> mkdir xyz | cd
Run Code Online (Sandbox Code Playgroud)
突然,提示中的路径带有前缀Microsoft.PowerShell.Core\FileSystem:::
PS Microsoft.PowerShell.Core\FileSystem::C:\Users\Rene\AppData\Local\Temp\xyz>
Run Code Online (Sandbox Code Playgroud)
这一变化也反映在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
Run Code Online (Sandbox Code Playgroud)
这是怎么回事以及如何关闭该前缀?
按相反顺序:
如何关闭该前缀?
简单,使用显式管道绑定!
mkdir xyz |cd -Path {$_.FullName}
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?
好问题!Get-ChildItem您在这里看到的是提供程序 cmdlet( 、Get-Item等Set-Location)如何实现管道绑定的副作用。
当您针对提供程序调用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
Run Code Online (Sandbox Code Playgroud)
当您使用下游提供程序 cmdlet(例如Set-Location/cd例如)构造管道语句时,它使用提供程序限定的PSPath值来数字绑定输入对象。
这可以通过以下方式观察到Trace-Command:
PS C:\> Trace-Command -Expression {Get-Item .|Set-Location} -Name ParameterBinding,MemberResolution -PSHost
Run Code Online (Sandbox Code Playgroud)
结果是(为了Get-Item简洁起见,我删除了详细信息):
mkdir xyz |cd -Path {$_.FullName}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,PowerShell 放弃绑定C:\到Set-Locations-Path参数,因为以某种方式将PSPath属性值绑定到-LiteralPath更合适?!
原因是该-LiteralPath参数被别名为PSPath,通过挖掘一点可以看出Get-Command:
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
Run Code Online (Sandbox Code Playgroud)
提供程序 cmdlet 的管道绑定以这种方式实现的真正原因有两个:
Path相关的意外后果
Get-Item -Path 'a[bcd]'例如,这Get-Item -LiteralPath 'a[bcd]'是两个截然不同的查询PSPath值意味着我们可以将位置切换到不同的提供者而不会丢失自动绑定:
PS Cert:\> $aFile |Get-Content 正常工作| 归档时间: |
|
| 查看次数: |
1510 次 |
| 最近记录: |