Reputation: 132118
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?
\
is the directory separator; but it's also an escape char in most languages. What do I do with it?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?
Upvotes: 1
Views: 1764
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.
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.
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).
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:
Verbatim (single-quoted) strings ('...'
) treat their content verbatim
Expandable (double-quoted) strings ("..."
) perform string interpolation ("expand" embedded variables and subexpressions, i.e replace them with their values).
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