Search code examples
powershelllsequivalent

How to do a ls -d in powershell


I need to list existing directories without listing files into them :

PS C:\Users\myHomeDIR> cat .\toto.txt
.\.config
C:\DA FI
PS C:\Users\myHomeDIR> cat .\toto.txt | dir | % FullName
C:\Users\myHomeDIR\.config\scoop
dir : Cannot find path 'C:\DA FI' because it does not exist.
At line:1 char:18
+ cat .\toto.txt | dir | % FullName
+                  ~~~
    + CategoryInfo          : ObjectNotFound: (C:\DA FI:String) [Get-ChildItem], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand

PS C:\Users\myHomeDIR> 

I expect this output instead (like LINUX ls -d would) :

C:\Users\myHomeDIR\.config
dir : Cannot find path 'C:\DA FI' because it does not exist.
At line:1 char:18
+ cat .\toto.txt | dir | % FullName
+                  ~~~
    + CategoryInfo          : ObjectNotFound: (C:\DA FI:String) [Get-ChildItem], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand


Solution

  • Use Get-Item rather than Get-ChildItem (one of whose built-in aliases is dir), as the former always reports the input items themselves, even if they're directories:

    Using its built-in gi alias, and gc rather than cat as a Get-Content alias:

    gc .\toto.txt | gi | % FullName
    

    As for the general question:

    • Get-Item is the equivalent of Unix ls -d

      • Like ls -d, Get-Item reports whatever paths it is given as themselves, i.e. it doesn't list the content of directories among the input paths (the latter is what ls does by default).

      • However, instead of reporting strings (names/paths only by default), Get-Item reports rich objects (System.IO.FileInfo and/or System.IO.DirectoryInfo instances) that allow flexible later processing (e.g., as shown in the question,
        % FullName extracts the full paths via the .FullName property, and .Name would yield just the name).

    • By contrast, Get-ChildItem -Directory, while seemingly a closer analog, works differently:

      • With literal input paths:

        • If a directory path is provided (by default: the current directory), it enumerates that directory's child directories - only, as themselves, i.e. without listing their content.

          • In other words: it enumerates the children of the target directory, but only if they are directories themselves.
        • With file paths as input, it acts the same as without -Directory (and, in this case, therefore like ls -d)

      • With wildcard expressions as input:

        • Only directories among the matching items are reported.

        • If you omit -Directory, files are reported too - and matching directories are still reported as themselves.

          • In other words: With a wildcard-based input path pattern - only - Get-ChildItem by default acts like ls -d; e.g., Get-ChildItem * basically acts the same as ls -d * (except that the former emits rich objects, whereas the latter emits strings (names only)).