einpoklum
einpoklum

Reputation: 132118

How to list contents of a specific directory in powershell?

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,

Upvotes: 1

Views: 1764

Answers (1)

mklement0
mklement0

Reputation: 439767

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)

Upvotes: 2

Related Questions