powershellget-childitem

How to change default view of FileInfo and DirectoryInfo?


I want to set a default strategy for displaying FileInfo and DirectoryInfo objects in Powershell to display only file paths.

Default behaviour

PS C:\Users\user> gci

    Directory: C:\Users\user

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----          2023-04-05     1:29                .cache
d----          2023-03-30    22:41                .dbus-keyrings
d----          2023-04-15    22:32                .docker
d----          2023-07-12    15:22                .gfclient
d----          2023-04-04     4:41                .gradle
d----          2023-04-16     0:30                .keras
-a---          2023-09-08    14:36          10629 _viminfo
-a---          2023-02-09    21:03              2 --help
-a---          2023-07-21    14:57          13675 .bash_history

Desired behaviour

PS C:\Users\user> gci
C:\Users\user\.cache
C:\Users\user\.dbus-keyrings
C:\Users\user\.docker
C:\Users\user\.gfclient
C:\Users\user\.gradle
C:\Users\user\.keras
C:\Users\user\_viminfo
C:\Users\user\--help
C:\Users\user\.bash_history

Desired behaviour can be achieved through appending | % fullname to command, which will print fullname property of every object in a pipe, but I need a powershell custom view which will do it every time objects of these types will end up in the end of pipe.

What I've tried

I assume my question is to be solved by creating custom view for appropriate object types and assigning this view as default.

This is format file I've created by changing default file:

<?xml version="1.0" encoding="utf-8"?>
<Configuration>
  <ViewDefinitions>
    <View>
      <Name>children</Name>
      <ViewSelectedBy>
        <TypeName>System.IO.DirectoryInfo</TypeName>
      </ViewSelectedBy>
      <!-- <GroupBy>
        <PropertyName>PSParentPath</PropertyName>
      </GroupBy> -->
      <TableControl>
        <TableHeaders>
          <TableColumnHeader />
        </TableHeaders>
        <TableRowEntries>
          <TableRowEntry>
            <Wrap />
            <TableColumnItems>
              <TableColumnItem>
                    <ScriptBlock>$_ | Resolve-Path -Relative</ScriptBlock>
                </TableColumnItem>
            </TableColumnItems>
          </TableRowEntry>
        </TableRowEntries>
        <HideTableHeaders>true</HideTableHeaders>
      </TableControl>
    </View>
    
    
    <View>
      <Name>childrenWithHardlink</Name>
      <ViewSelectedBy>
        <TypeName>System.IO.DirectoryInfo</TypeName>
      </ViewSelectedBy>
      <!-- <GroupBy>
        <PropertyName>PSParentPath</PropertyName>
      </GroupBy> -->
      <TableControl>
        <TableHeaders>
          <TableColumnHeader />
        </TableHeaders>
        <TableRowEntries>
          <TableRowEntry>
            <Wrap />
            <TableColumnItems>
              <TableColumnItem>
                <ScriptBlock>$_ | Resolve-Path -Relative</ScriptBlock>
              </TableColumnItem>
            </TableColumnItems>
          </TableRowEntry>
        </TableRowEntries>
        <HideTableHeaders>true</HideTableHeaders>
      </TableControl>
    </View>
    
    
    <View>
      <Name>children</Name>
      <ViewSelectedBy>
        <TypeName>System.IO.DirectoryInfo</TypeName>
      </ViewSelectedBy>
      <!-- <GroupBy>
        <PropertyName>PSParentPath</PropertyName>
      </GroupBy> -->
      <ListControl>
        <ListEntries>
          <ListEntry>
            <ListItems>
              <ListItem>
                <ScriptBlock>$_ | Resolve-Path -Relative</ScriptBlock>
              </ListItem>
            </ListItems>
          </ListEntry>
          <ListEntry>
            <EntrySelectedBy>
              <TypeName>System.IO.FileInfo</TypeName>
            </EntrySelectedBy>
            <ListItems>
              <ListItem>
                <ScriptBlock>$_ | Resolve-Path -Relative</ScriptBlock>
              </ListItem>
            </ListItems>
          </ListEntry>
        </ListEntries>
        <!-- <HideTableHeaders>true</HideTableHeaders> -->
      </ListControl>
    </View>
    <View>
      <Name>children</Name>
      <ViewSelectedBy>
        <TypeName>System.IO.DirectoryInfo</TypeName>
      </ViewSelectedBy>
      <!-- <GroupBy>
        <PropertyName>PSParentPath</PropertyName>
      </GroupBy> -->
      <WideControl>
        <WideEntries>
          <WideEntry>
            <WideItem>
              <ScriptBlock>$_ | Resolve-Path -Relative</ScriptBlock>
            </WideItem>
          </WideEntry>
          <WideEntry>
            <EntrySelectedBy>
              <TypeName>System.IO.DirectoryInfo</TypeName>
            </EntrySelectedBy>
            <WideItem>
              <ScriptBlock>$_ | Resolve-Path -Relative</ScriptBlock>
            </WideItem>
          </WideEntry>
        </WideEntries>
        <!-- <HideTableHeaders>true</HideTableHeaders> -->
      </WideControl>
    </View>
  </ViewDefinitions>
</Configuration>

This is how it is loaded: Update-FormatData -PrependPath C:\Users\user\Desktop\format.ps1xml

After that, instead of desired behavior, gci produces this:

PS C:\Users\user> gci

..\.cache
..\.dbus-keyrings
..\.docker
..\.gfclient
..\.gradle
..\.keras

LastWriteTime : 2023-09-08 14:36:29
Length        : 10629
Name          : _viminfo


LastWriteTime : 2023-07-21 14:57:46
Length        : 13675
Name          : .bash_history


LastWriteTime : 2023-07-20 13:15:58
Length        : 101
Name          : .gitconfig


LastWriteTime : 2023-07-05 19:27:42
Length        : 2200
Name          : .h2.server.properties

It applies new view settings only for directories, not for files.

How should I change format.ps1xml? Or how do I get what I need in different way?


Solution

  • As @santiago-squarzon pointed out, answer to another question on SO has a better template for a format.ps1xml file. This is my final version:

    <?xml version="1.0" encoding="utf-8"?>
    <Configuration>
      <ViewDefinitions>
        <View>
          <Name>CustomIODisplay</Name>
          <ViewSelectedBy>
            <TypeName>System.IO.DirectoryInfo</TypeName>
            <TypeName>System.IO.FileInfo</TypeName>
          </ViewSelectedBy>
          <TableControl>
            <TableHeaders>
                <TableColumnHeader>
                    <Label>Path</Label>
                </TableColumnHeader>
                <!-- <TableColumnHeader>
                    <Label>Length</Label>
                </TableColumnHeader> -->
            </TableHeaders>
            <TableRowEntries>
              <TableRowEntry>
                <Wrap />
                <TableColumnItems>
                  <TableColumnItem>
                        <ScriptBlock>
                        # text colors: https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences#text-formatting
                        if ($_.PSIsContainer) {
                            $colors = @()
                            # $colors += '32'   #greenFg
                            $colors += '44' #blueBg
                            $colors = $colors -join ';'
                            
                        }
                        $e = [char]27
                       "$e[${colors}m$($_.FullName)${e}[0m"
                        </ScriptBlock>
                    </TableColumnItem>
                    <!-- <TableColumnItem>
                        <ScriptBlock>$_.length</ScriptBlock>
                    </TableColumnItem> -->
                </TableColumnItems>
              </TableRowEntry>
            </TableRowEntries>
            <HideTableHeaders>true</HideTableHeaders>
          </TableControl>
        </View>
      </ViewDefinitions>
    </Configuration>
    

    Import it: Update-FormatData -PrependPath .\formatGci2.ps1xml (it changes view only for current session, add it to pwsh profile if auto-load is needed).

    It achieves desired behavior (prints only fullnames), but also changes bg color for directories to blue color, as it is in default view. Also it has commented-out columnHeader and columnItem so it would be easy to add a new column if needed.