Reputation: 516
Most likely there's something fundamental I don't understand about PowerShell. I really don't like when writing even medium sized pipes, where grabbing a property breaks the workflow by having to put parens around the statement up to that point, for eg.
(Get-ChildItem ~\.gitconfig).Length
This is tedious. Because Length
looks very much like a property, one would think
Get-ChildItem ~\.gitconfig | Get-ItemPropertyValue -Name Length
would work. However, it does not. Taking a look at the interface of the System.IO.FileSystemInfo
object returned by the File System PSDrive provider, one sees that it doesn't have a Length property. It does have a FullName property though, hence
Get-ChildItem ~\.gitconfig | Get-ItemPropertyValue -Name FullName
works as expected. To retrieve the size (Length
) of a file using the pipe, one has to use Select-Object
with the -ExpandProperty
like
Get-ChildItem ~\.gitconfig | Select-Object -ExpandProperty Length
How does one know up front whether placing a .
after an object and iterating through the results of tab completion, if the entry is an object or a property? It's very annoying that even common operations are confusing as hell, given for instance that reading environmental variables goes by
Get-Item -Path Env:\USERNAME
returns
Name Value
---- -----
USERNAME mnagy
If it's an item, Get-ItemProperty
and Get-ItemPropertyValue
must play a role here. Because of the Name:Value structure of the result, newcomers might be intrigued to obtain the actual value saying
Get-Item -Path Env:\USERNAME | Get-ItemPropertyValue
or actually reading how Get-ItemPropertyValue
should be used modify the query to
Get-ItemPropertyValue -Path Env:\ -Name USERNAME
which in fact results in
Get-ItemPropertyValue : Cannot use interface. The IPropertyCmdletProvider interface is not supported by this provider.
At line:1 char:1
+ Get-ItemPropertyValue -Path Env:\ -Name USERNAME
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotImplemented: (:) [Get-ItemPropertyValue], PSNotSupportedException
+ FullyQualifiedErrorId : NotSupported,Microsoft.PowerShell.Commands.GetItemPropertyValueCommand
This entire construction seems utterly inconsistent to me and most vexing, but hopefully not by design, but because I look at it from the wrong angle.
Upvotes: 0
Views: 1755
Reputation: 17347
To your first note: Length
, for .hg
directoy, worked form me just fine (giving you the number of files within):
Ps C:\> (Get-ChildItem .hg).Length
18
I tend to use get-member
to check what is supported and what is not.
If I check it for my directory reports
:
(Get-ChildItem reports) | gm
TypeName: System.IO.FileInfo
Name MemberType Definition
---- ---------- ----------
LinkType CodeProperty System.String LinkType{get=GetLinkType;}
Mode CodeProperty System.String Mode{get=Mode;}
Target CodeProperty System.Collections.Generic.IEnumerable`1[[System.String, mscorlib, Version=...
AppendText Method System.IO.StreamWriter AppendText()
CopyTo Method System.IO.FileInfo CopyTo(string destFileName), System.IO.FileInfo CopyTo(s...
Create Method System.IO.FileStream Create()
CreateObjRef Method System.Runtime.Remoting.ObjRef CreateObjRef(type requestedType)
CreateText Method System.IO.StreamWriter CreateText()
Decrypt Method void Decrypt()
Delete Method void Delete()
Encrypt Method void Encrypt()
Equals Method bool Equals(System.Object obj)
GetAccessControl Method System.Security.AccessControl.FileSecurity GetAccessControl(), System.Secur...
GetHashCode Method int GetHashCode()
GetLifetimeService Method System.Object GetLifetimeService()
GetObjectData Method void GetObjectData(System.Runtime.Serialization.SerializationInfo info, Sys...
GetType Method type GetType()
InitializeLifetimeService Method System.Object InitializeLifetimeService()
MoveTo Method void MoveTo(string destFileName)
Open Method System.IO.FileStream Open(System.IO.FileMode mode), System.IO.FileStream Op...
OpenRead Method System.IO.FileStream OpenRead()
OpenText Method System.IO.StreamReader OpenText()
OpenWrite Method System.IO.FileStream OpenWrite()
Refresh Method void Refresh()
Replace Method System.IO.FileInfo Replace(string destinationFileName, string destinationBa...
SetAccessControl Method void SetAccessControl(System.Security.AccessControl.FileSecurity fileSecurity)
ToString Method string ToString()
PSChildName NoteProperty string PSChildName=jv_libgdbs_tests-20180822-Test.xml
PSDrive NoteProperty PSDriveInfo PSDrive=C
PSIsContainer NoteProperty bool PSIsContainer=False
PSParentPath NoteProperty string PSParentPath=Microsoft.PowerShell.Core\FileSystem::C:\prg_sdk\stx8-j...
PSPath NoteProperty string PSPath=Microsoft.PowerShell.Core\FileSystem::C:\prg_sdk\stx8-jv_swin...
PSProvider NoteProperty ProviderInfo PSProvider=Microsoft.PowerShell.Core\FileSystem
Attributes Property System.IO.FileAttributes Attributes {get;set;}
CreationTime Property datetime CreationTime {get;set;}
CreationTimeUtc Property datetime CreationTimeUtc {get;set;}
Directory Property System.IO.DirectoryInfo Directory {get;}
DirectoryName Property string DirectoryName {get;}
Exists Property bool Exists {get;}
Extension Property string Extension {get;}
FullName Property string FullName {get;}
IsReadOnly Property bool IsReadOnly {get;set;}
LastAccessTime Property datetime LastAccessTime {get;set;}
LastAccessTimeUtc Property datetime LastAccessTimeUtc {get;set;}
LastWriteTime Property datetime LastWriteTime {get;set;}
LastWriteTimeUtc Property datetime LastWriteTimeUtc {get;set;}
Length Property long Length {get;}
Name Property string Name {get;}
BaseName ScriptProperty System.Object BaseName {get=if ($this.Extension.Length -gt 0){$this.Name.Re...
VersionInfo ScriptProperty System.Object VersionInfo {get=[System.Diagnostics.FileVersionInfo]::GetVer...
How does one know up front whether placing a . after an object and iterating through the results of tab completion, if the entry is an object or a property?
You check it with with Get-Member
.
For the Get-Item -Path Env:\USERNAME
you can again check:
PS C:\> Get-Item -Path Env:\USERNAME | gm
TypeName: System.Collections.DictionaryEntry
Name MemberType Definition
---- ---------- ----------
Name AliasProperty Name = Key
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
PSDrive NoteProperty PSDriveInfo PSDrive=Env
PSIsContainer NoteProperty bool PSIsContainer=False
PSPath NoteProperty string PSPath=Microsoft.PowerShell.Core\Environment::USERNAME
PSProvider NoteProperty ProviderInfo PSProvider=Microsoft.PowerShell.Core\Environment
Key Property System.Object Key {get;set;}
Value Property System.Object Value {get;set;}
Now check the USERNAME (you see the key you are asking and its value):
PS C:\> (Get-Item -Path Env:\USERNAME).key
USERNAME
PS C:\> (Get-Item -Path Env:\USERNAME).value # my login
gurun
Upvotes: 1