powershellformatting

Use a PowerShell script to display just the alias name column


I'm fairly new to PowerShell scripting after years of Unix/Linux scripting, and I'm still trying to get the handle of object output. I am trying to run the Get-Alias command to return just the column "Name."

When I try to select just the column "name", I either get the whole Get-Alias output, or errors. The script/ command line I am trying to use is: Get-Alias | Format-Table

When I add Select-Object logic, it either cuts off the name of the alias and leaves off the command name or the Select-Object logic is just ignored. I'm sure the solution is simple.


Solution

  • tl;dr:

    Get-Alias | Select-Object -ExpandProperty DisplayName
    

    Output:

    ? -> Where-Object
    cd -> Set-Location
    ...
    
    

    That is, the true property name underlying the Name display column is DisplayName.


    PowerShell's default output formatting sometimes uses column names that differ from or the underlying objects' property names (which is the case here) and/or use values that are calculated.

    What shows as column Name by default is actually the underlying objects' .DisplayName property, whereas the true .Name property contains just the alias' own name.

    You can inspect the members (properties and methods) of an object's type via Get-Member or, to see both the property (but not method) names and their concrete values for a given object, pipe to Format-List *:

    Get-Alias | Select-Object -First 1 | Format-List *
    

    Output:

    HelpUri             : https://go.microsoft.com/fwlink/?LinkID=113423
    ResolvedCommandName : Where-Object
    DisplayName         : ? -> Where-Object
    ReferencedCommand   : Where-Object
    ResolvedCommand     : Where-Object
    Definition          : Where-Object
    Options             : ReadOnly, AllScope
    Description         :
    OutputType          : {}
    Name                : ?
    CommandType         : Alias
    Source              :
    Version             :
    Visibility          : Public
    ModuleName          :
    Module              :
    RemotingCapability  : None
    Parameters          : {[InputObject, System.Management.Automation.ParameterMetadata], [FilterScript, System.Management.Automation.ParameterMetadata], [Property,
                          System.Management.Automation.ParameterMetadata], [Value, System.Management.Automation.ParameterMetadata]...}
    ParameterSets       :
    

    Optional reading: How to inspect a given type's formatting data:

    For background information, see Get-Help about_Format.ps1xml.

    Get-Alias outputs [System.Management.Automation.AliasInfo] instances (as Get-Member will tell you).

    Using the Get-FormatData cmdlet you can inspect a type's formatting data:

    Caveat: Not all formatting data in effect is by default reported by Get-FormatData for backward-compatibility reasons - see this GitHub issue; notable omissions are [System.IO.FileInfo] and [System.IO.DirectoryInfo], as returned by Get-ChildItem / Get-Item ; in short, to see all formatting data in effect for the PowerShell version at hand, use:

    Get-FormatData -PowerShellVersion $PSVersionTable.PSVersion [...]
    

    Somewhat ironically, there isn't any custom formatting data defined for the System.Management.Automation.ExtendedTypeDefinition instances that Get-Format outputs, and the default formatting isn't helpful.

    Currently, the simplest way to inspect formatting data is to pipe to the Format-Custom cmdlet, which provides an informal, human-readable representation of the internal structure of objects:

    # It is best to send this to a file and open that file in a text editor for perusal.
    $prev, $FormatEnumerationLimit = $FormatEnumerationLimit, [int]::MaxValue
    Get-FormatData System.Management.Automation.AliasInfo | Format-Custom -Depth 10
    $FormatEnumerationLimit = $prev
    

    Note:

    The output will look vaguely like JSON and is suited to visual inspection only, not programmatic processing.

    You'll see one or more of the following blocks:

    class ExtendedTypeDefinition
    {
      TypeNames =
        [
          <typeName>
        ]
    
      FormatViewDefinition =
        [
          class FormatViewDefinition
          {
            Name = <formatName>
            Control =
              class <viewType>Control
            ...
          }
          class FormatViewDefinition
          {
            Name = <formatName>
            Control =
              class <viewType>Control
            ...
          }
    }
    

    Note that the output may contain duplicate information, as it does in the case of System.Management.Automation.AliasInfo (because the formatting information is repeated for all other command types that share the same formatting), but it is sufficient to examine the first class <viewType>Control instance of interest.

    Specifically, here's an excerpt from the first class TableControl block:

    class TableControl   # Defines the format for Format-Table
    {
      Headers =   # The table headers (column names and column properties)
          ...
          class TableControlColumnHeader # The "Name" column *header*
          {
            Label = Name
            Alignment = Undefined
            Width = 50
          }
          ...
        ]
    
      Rows =  # The table rows (underlying or calculated property values)
        [
          class TableControlRow
          {
            Columns =
              [
                ...
                class TableControlColumn  # The "Name" column *value*
                {
                  Alignment = Undefined
                  DisplayEntry =
                    class DisplayEntry
                    {
                      ValueType = ScriptBlock  #  A *calculated* property
                      Value =
                                                      if ($_.CommandType -eq "Alias")
                                                      {
                                                        $_.DisplayName
                                                      }
                                                      else
                                                      {
                                                        $_.Name
                                                      }
    
                    }
                  FormatString =
                }
                ...
        ]
        ...
    
    

    Note that the header and column-value definitions are matched positionally; e.g., the second TableControlColumn instance defines the value for the second TableControlColumnHeader instance.

    The above explains why, even though the column is entitled "Name", it is an alias' .DisplayName property that is displayed, whereas all the other command types are represented by their .Name property, by way of the embedded script block (the piece of PowerShell code in which $_ represents the input object at hand).

    Presumably, the decision to show the .DisplayName for aliases was made to provide more helpful information by default, but the discrepancy between the column name and underlying property name can certainly lead to confusion.

    Note that there is also a dedicated table view for type [System.Management.Automation.AliasInfo] that (a) defines only two columns, and (b) calls the .DisplayProperty column values by their true name. However, as of the PowerShell versions listed above, this view is preempted by the multi-type definition discussed above and effectively ignored.