2

I'm rather baffled by Powershell in general. Very weird. Anyway, I've read:

Powershell's equivalent to Linux's: ls -al

so I now know how to list the contents of the current directory. But how can I list the contents of an arbitrary directory?

Specifically,

  • How do I type in the path I want to check?

    • in Windows, \ is the directory separator; but it's also an escape char in most languages. What do I do with it?
    • Do I need single-quotes? Double-quotes? No-quotes?
  • Where do I place the argument relative to the switches? After, like I'm used to, or rather before?

  • If I want to use an environment variable, or a powershell variable, as part of the path to list - how do I do that?

einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • I realized I missed some of your questions originally. I've restructured the answer into two sections: Section one contains general information about `Get-ChildItem`, how parameter syntax is described in PowerShell's help system, and how examples can be printed. Section two answers your specific questions in a manner that may help readers coming from POSIX-compatible shells such as Bash. – mklement0 Jun 06 '22 at 19:35

1 Answers1

2

General PowerShell information and examples:

PowerShell-native commands, including user-authored ones that opt in, have standardized parameter syntax and binding rules, so the following, focused on Get-ChildItem, applies generally:

  • See the help topic for Get-ChildItem, which describes the command's purpose, syntax, and individual parameters, along with showing examples.

    • If you have offline help installed (true by default in Windows PowerShell; installable on demand via Update-Help in PowerShell (Core) 7+), you can also print the examples with Get-Help -Example Get-ChildItem | more
  • As for how to generally read the notation describing the supported parameters listed under the SYNTAX heading of cmdlet help topics, which PowerShell calls syntax diagrams, see the conceptual about_Command_Syntax help topic.

  • Offline, you can print the syntax diagrams for PowerShell-native commands with standard switch -? or by passing the command name to Get-Command -Syntax (Get-ChildItem -? or Get-Command -Syntax Get-ChildItem). To also access the help text offline, you may have to install local help first, as described above.

Examples:

# The following commands all pass "\" (the [current drive's] root dir)
# to the -Path parameter.
# Note: 
#  * "\" is NOT special in PowerShell, so it needs no escaping.
#    PowerShell allows use of "/" instead even on Windows.
#  * -Path arguments are interpreted as wildcard patterns, whether
#     quoted or not. You may pass *multiple* paths / patterns.
#  * Switch -Force - which, as all switches - can be placed anywhere
#    among the arguments, requests that *hidden* items be listed too.

Get-ChildItem -Path \ -Force
Get-ChildItem \ -Force  # ditto, with *positional* param. binding
'\' | Get-ChildItem     # ditto, via the pipeline.
Get-ChildItem / -Force  # ditto, with "/" as alternative to "\"

# To force interpretation as a *literal* path - which matters for
# paths that contain "[" chars. - use -LiteralPath.
# Here too you may pass *multiple* paths.
Get-ChildItem -LiteralPath \ -Force

# Quoting is needed for paths with spaces, for instance.

# Single-quoting treats the string *verbatim*:
Get-ChildItem 'C:\path\to\dir with spaces'

# Double-quoting *expands* (interpolates) variable references
# and subexpressions.
Get-ChildItem "$HOME\dir with spaces"

# A variable alone can be used as-is, without double-quoting, even
# if its value contains spaces.
Get-ChildItem $HOME

To answer your specific questions, for readers who come from POSIX-compatible shells such as Bash:

How do I type in the path I want to check?

Get-ChildItem offers two ways to specify one or more input paths, as most file-processing cmdlets in PowerShell do:

  • -Path accepts one or more names or paths that are interpreted as a wildcard pattern.

    • Note that - unlike in POSIX-compatible shells such as Bash - it does not matter whether the path is unquoted or not; e.g., Get-ChildItem -Path *.txt, Get-ChildItem "*.txt", and Get-ChildItem '*.txt' are all equivalent; more on that below (note the incidental omission of -Path in the latter two calls, which makes "*.txt" and '*.txt' bind positionally to the first positional parameter, -Path).
  • -LiteralPath accepts one or more names or paths that are assumed to refer to existing file-system items literally (verbatim).

    • Given that literal paths on Unix-like platforms usually do not contain * and ? characters and on Windows cannot, use of -LiteralPath for disambiguation is usually only necessary for paths that contain [ (and possibly also ]), given that PowerShell's wildcard pattern language also supports character sets and ranges (e.g. [ab] and [0-9]).

    • Binding to -LiteralPath via an argument requires explicit use of -LiteralPath, i.e. use of a named argument; e.g., Get-ChildItem -LiteralPath foo

    • However, supplying System.IO.FileInfo and/or System.IO.DirectoryInfo instances (such as output by (another) Get-ChildItem or Get-Item call) via the pipeline DOES bind to -LiteralPath, as explained in this answer.

in Windows, \ is the directory separator; but it's also an escape char in most languages. What do I do with it?

In PowerShell \ is not an escape character, so \ instances are treated as literals and do not require escaping; it is `, the so-called backtick that serves as the escape character in PowerShell - see the conceptual about_Special_Characters help topic.

Note, however, that PowerShell generally allows you to use \ and / in paths interchangeably, so that, e.g., Get-ChildItem C:/Windows works just fine.

Where do I place the argument relative to the switches? After, like I'm used to, or rather before?

Note:

  • All parameters have names in PowerShell - that is, there is no POSIX-like distinction between options (e.g. -l and operands (value-only arguments, such as the / in ls -l /).

  • A command may declare parameters that may also be passed by value only, positionally, meaning that prefixing the value with the parameter name is then optional (e.g., Get-Path / as shorthand for Get-Path -Path /).

Only parameters that require a value (argument) can potentially be passed as values only - depending on the parameter declaration of the target command - in which case their order matters:

  • Value-only arguments are called positional arguments, and they bind in order to those parameters of the target command that are declared as positional, if any - see this answer for how to discover which of a given command's parameters are positional ones.

  • Prefixing a value by its target parameter (e.g., -LiteralPath /some/path) makes it a named argument.

A switch (flag) in PowerShell, such as -Force, is a special parameter type - Boolean in nature - that by definition requires passing it as a named argument, typically without a value (though you can attach a value, e.g. -Force:$true or -Force:$false - note that : is then required to separate the parameter name from its value; see this answer for details).

  • As an aside: Unlike POSIX-compliant utilities, PowerShell does not support parameters with optional values of any other type - see this answer.

Since PowerShell allows named arguments to be specified in any order, the implication is that you're free to place by-definition-named switch arguments such as -Force anywhere on the command line.

In short: Order only matters among positional (unnamed) arguments in PowerShell.

See the conceptual about_Parameters help topic for more information.

Do I need single-quotes? Double-quotes? No-quotes?

A path (parameter value in general) needs quoting:

  • if it contains PowerShell metacharacters, notably spaces; e.g. C:\path\to\foo needs no quoting, whereas C:\path with spaces\to\foo does.

  • if it starts with a subexpression ($(...)), in which case you need double-quoting, i.e. "..." (see below) - though you may choose to always use "..."-quoting for paths involving subexpressions or variable references.

  • Note that PowerShell has no concept that is the equivalent of the so-called shell expansions in POSIX-compatible shells such as Bash; therefore, whether a given argument is quoted or not makes no semantic difference (assuming it doesn't require quoting); as noted above, *.txt, '*.txt' and "*.txt" are all equivalent, and it is the target command, not PowerShell itself, that interprets the pattern - see this answer for more information.

If quoting is needed:

If I want to use an environment variable, or a powershell variable, as part of the path to list - how do I do that?

To use such variables as-is, no quoting is needed (even if the values contain spaces):

# PowerShell variable:
Get-ChildItem -LiteralPath $HOME

# Environment variable, e.g. on Windows:
Get-ChildItem -LiteralPath $env:USERPROFILE

To make a variable (or expression) part of a larger string, embed it in an expandable (double-quoted) string ("..."); e.g.:

Get-ChildItem -LiteralPath "$HOME/Desktop"

Note:

  • Embedding the output from expressions or commands requires use of $(...), the subexpression operator; e.g.
    Get-ChildItem "$(Get-Variable -ValueOnly Home)/Desktop"; for a complete overview of PowerShell's expandable strings (string interpolation), see this answer.

  • Situationally, such as in the example above, omitting the "..." quoting would work too - see this answer for more information.

Additionally and alternatively, PowerShell allows you to use (...), the grouping operator to pass the result of arbitrary expressions and commands as arguments; the following is the equivalent of the command above:

Get-ChildItem -LiteralPath ($HOME + '/Desktop')

Alternatively, using the Join-Path cmdlet:

Get-ChildItem -LiteralPath (Join-Path $HOME Desktop)
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • +1 for effort, but I have to admit - the length of (the second part of ) your answer is somewhat of a demotivator :-( – einpoklum Jun 06 '22 at 19:43
  • 1
    @einpoklum, yes, it's long, but comprehensive - and necessary, if you want to invest the time to learn PowerShell properly. Not everyone does, and my hope is that the annotated examples in the first section are enough for those that don't. Regardless of what category you fall into, let me know if either section is missing something. – mklement0 Jun 06 '22 at 19:48