10

I don't use Powershell nor Linux very often so I am unsure of what: ls -al would be in Powershell "terms". I tried to find something but it said there wasn't an equivalent command in Powershell. Seems odd so I figured I would ask quick.

SomethingDark
  • 13,229
  • 5
  • 50
  • 55
butlertj10
  • 103
  • 1
  • 1
  • 4
  • A strict equivalent might not exist. Since Linux and Windows are different operating systems – Basile Starynkevitch Feb 19 '21 at 13:53
  • @BasileStarynkevitch, indeed there is no _strict_ equivalent, but given that [PowerShell (Core) 7+](https://github.com/PowerShell/PowerShell) runs on Linux (and macOS) too, this isn't so much about different platforms, I presume, but about a _Powershell-idiomatic way_ of getting _analogous_ functionality (and on macOS and Linux you can just call `ls -al` directly). – mklement0 Feb 19 '21 at 14:05

1 Answers1

16

The ls Unix utility's options you're using:

  • -a option includes hidden items, which on Unix-like platforms are file-system items whose name starts with .

  • -l requests the so-called long format, which produces tabular output that includes the file-system items' mode, user and group ownership, the last-write timestamp, the item size, and its name.

The PowerShell equivalent is:

Get-ChildItem -Force
  • Get-ChildItem's -Force switch includes hidden items in the output - although, unlike with ls, the . and .. entries representing the target directory itself and its parent directory are not included (which makes it the equivalent of the more useful -A ls option).

  • The equivalent of long format formatting is used by default; if, conversely, you're interested in file names (relative paths) only, use the -Name switch.

  • Note: By default, Get-ChildItem targets the current location (directory); to specify an input path explicitly, use either the -Path parameter - for wildcard patterns - or the -LiteralPath parameter - for literal (verbatim) paths. The first positional argument (one not prefixed by a parameter names) implicitly binds to -Path; e.g., the following command targets the current user's home directory:

    Get-ChildItem -Force -LiteralPath $HOME
    

See the bottom section for shortening this command and defining a convenience "alias" (function).


There's one fundamental difference between ls and Get-ChildItem, however:

  • ls outputs formatted text, and for that reason parsing its output is generally discouraged.

  • In PowerShell, formatting is separated from data and it is objects, not strings that are output.

    • That is, irrespective of the rich display formatting that Get-ChildItem output presents in the terminal, its actual output are objects of type System.IO.FileInfo and System.IO.DirectoryInfo, which can safely be used for further programmatic processing if captured in a variable, sent to other PowerShell comments through a pipeline, or used in an expression.
  • For instance, expression (Get-ChildItem -Force).FullName outputs the full paths of all items in the current directory.


For interactive convenience (you shouldn't do that in scripts), you can use built-in aliases and unambiguous parameter-name prefixes to shorten the command:

gci -fo

gci is built-in alias for Get-ChildItem, and its name follows PowerShell's naming conventions, where each so-called approved verb also has an approved 1-2 letter alias form; running Get-Verb Get reveals that the approved Get verb's alias form is g; while the noun part isn't formally regulated, remembering that ci stands for ChildItem should be easy.

-fo is the shortest parameter-name prefix that unambiguously refers to the -Force switch (just -f alone could also refer to -Filter[1])

  • Note: Some parameters themselves have actual aliases, such as -h for -Hidden or -ad for -Directory, but -Force does not.
  • Unlike unambiguous parameter-name prefixes, which can become ambiguous over time if new parameters are added to a command, parameter aliases are safe to use in scripts, although for readability the full names are preferable.

To see all aliases defined for a given command (Get-ChildItem in this example):

PS> Get-Alias -Definition Get-ChildItem

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Alias           dir -> Get-ChildItem                                          
Alias           gci -> Get-ChildItem                                          

To limit output to built-in aliases, i.e. to exclude aliases defined by other modules or $PROFILE scripts, run pwsh -noprofile { Get-Alias -Definition Get-ChildItem } (in Windows PowerShell, use powershell instead of pwsh.

  • The above shows the output on macOS and Linux.
  • On Windows you will see that ls is another built-in alias.
    • This is a legacy alias from the time PowerShell was a Windows-only shell, and is best avoided:

      • In general, aliases take precedence over external programs with the same name, and it isn't a good idea to shadow (override) a platform's standard command-line utilities; while that doesn't apply to alias ls on Windows, it does in other cases, namely where (shadows where.exe) and sc (Windows PowerShell-only, shadows sc.exe)

      • Specifically, given that the real ls Unix utility and Get-ChildItem have such vastly different syntax (and behavior), exposing the latter as ls is likely to cause confusion.

Therefore, it is advisable to stick to those aliases that are abbreviated forms of the PowerShell command names, such as gci for Get-ChildItem, and gc for Get-Content. While that doesn't initially help with transitioning from familiar names such as ls / dir and cat, the fact that PowerShell cmdlet names as well as their abbreviated aliases are systematic and convention-based makes it easier to memorize them going forward.

Defining a convenience "alias" with preset arguments, using a function:

POSIX-compatible shells such as bash allow you to define aliases with preset arguments, such as alias ll='ls -al'

By contrast, aliases in PowerShell are mere name mappings and you need to declare a function instead (which you can add to your $PROFILE file for availability in future session):

# Equivalent of bash alias `alias ll='ls -al'`
function ll { ls -al @args }

Or, an analogous gcih function (h denoting hidden) based on Get-ChildItem:

function gcih { Get-ChildItem -Force @args }

See this answer for more information about aliases vs. functions in PowerShell, including how to create more sophisticated wrapper functions.


[1] Conceptually, it could also refer to the -File parameter, but technically the latter is a dynamic parameter, specific to PowerShell's file-system provider, and is therefore not being considered during the ambiguity check.

mklement0
  • 382,024
  • 64
  • 607
  • 775