5

I know that both are used in PowerShell but for different contexts.

On the internet there is a paucity of information on this topic and the only site that talks about it (without making me understand the concept) is:
https://www.rlmueller.net/PowerShellEscape.htm

I am a beginner with PowerShell, I am recently approaching it.
A use case of the \ escape came up in the answer to this other topic of mine:
PowerShell removes multiple consecutive whitespaces when I pass arguments to a nested Start-Process command

Is there anyone who can explain to me in detail the difference between the escape backtick ` and backslash \ in PowerShell, with examples and use cases?

At least one source is welcome, but it is not mandatory.

mklement0
  • 382,024
  • 64
  • 607
  • 775
Mario Palumbo
  • 693
  • 8
  • 32

2 Answers2

11

vonPryz's helpful answer covers the PowerShell-internal angle well; let me attempt a systematic summary that includes the PowerShell CLI angle, as well as passing arguments with embedded " to external programs:

Inside a PowerShell session, the only escape character is ` (the so-called backtick), in the following contexts:

  • Inside an expandable string ("...", double quoted), but not inside a verbatim string ('...', single-quoted); for the supported escape sequences, see the conceptual about_Special_Characters help topic:

    # " must be escaped; escape sequence `n expands to a newline.
    "3`" of`nrain" 
    
  • In unquoted command arguments:

    # > must be escaped to write verbatim 'a>b', 
    # since outside a quoted string an unescaped > is a redirection.
    Write-Output a`>b  
    
  • For line-continuations:

    # Spread the Get-Date call across two lines.
    # Important: ` must be the *very last char* on the line.
    Get-Date `
      -Year 2525
    
  • Note: Various subsystems, whether PowerShell-specific or not, may have their own escaping rules, such as \ in regular expressions and ` in wildcard expressions. Since arguments to those subsystems are delivered via PowerShell strings, it's best to use verbatim string literals, so as to avoid confusion between PowerShell's own string interpolation and what the target subsystem ends up seeing; e.g. 'A $50 fine.' -match '\$50' (\ is needed to treat regex metacharacter $ literally).


When PowerShell is called from the outside, via its CLI, different rules apply, possibly in addition:

In order to adhere to widely used convention for CLIs (command-line interfaces, programs that accept arguments via a command line) on Windows:

  • In calls to powershell.exe, the Windows PowerShell CLI, " characters must be escaped with a backslash - i.e. as \" - in order to be preserved during parsing of the original command line.

  • pwsh.exe, the CLI of the cross-platform, install-on-demand PowerShell (Core) 7+ edition, now commendably alternatively accepts ""[1] in lieu of \", which makes calls from cmd.exe more robust. To get the same robustness in Windows PowerShell - from cmd.exe only - use "^"" (sic).
    Note that - unlike \" - these escape sequences only work inside an (unescaped) "..." string (e.g., pwsh.exe -c " ""you & I"" " or powershell.exe -c " "^""you & I"^"" "

By contrast, unescaped " have syntactic function on the command line and tell PowerShell where the boundaries between arguments are; these " instances are removed during command-line parsing.

This ensures that outside callers that merely want to invoke a PowerShell script file (.ps1) with arguments, using the -File parameter, can use the conventional syntax and needn't special-case calls to PowerShell's CLI.

However, if you pass a string containing PowerShell code to the CLI, using the -Command parameter, what PowerShell ends up interpreting obviously must be syntactically valid PowerShell code.

Caveat: If you specify neither -Command nor -File:

  • powershell.exe defaults to -Command
  • pwsh.exe now defaults to -File

For the differences between -File and -Command calls and when to use which, see this answer.

If you use -Command, there are two, sequential parsing stages:

  • The command-line parsing stage, where syntactic (unescaped) " are removed, and escaped \" (or "") turn into literal ".

  • The result of this stage is then parsed as PowerShell code, as it would be from inside a PowerShell session.

Therefore, you may situationally have to combine \ and `-escaping; e.g. (call from cmd.exe):

C:>powershell.exe -Command " \"3`\" of snow as of $(Get-Date)\" "

3" of snow as of 11/04/2021 14:13:41

Note the use of `\" in order to make PowerShell see `", i.e. a properly escaped " inside a "..." string, after command-line parsing.

Alternatively, depending on the specifics of the command(s) you pass to -Command, using embedded '...' quoting may be an option, which simplifies matters, because ' chars. don't require escaping:

C:>powershell.exe -Command " '3\" of snow as of today.' "

3" of snow as of today.

Given that '...' strings in PowerShell are verbatim strings, use of '...' is only an option if you don't require string interpolation (such as the $(Get-Date) subexpression in the prior example).


Escaping " when calling external programs from PowerShell:

As a shell, it is PowerShell's job to pass the arguments that were passed based on its syntax rules to a target executable, so that the verbatim values that result from PowerShell's parsing are passed in a way that makes the target executable see them as such. In other words: PowerShell should perform any required escaping automatically, behind the scenes. (Unlike cmd.exe, PowerShell cannot just pass its own argument syntax through as-is, because external CLIs cannot be expected to understand '...' strings (single-quoting) or `-escaping).

To use a simply example: Passing '3" of snow' should be passed as "3\" of snow" behind the scenes, based on the most widely used escaping convention.

Sadly, up to PowerShell 7.2.x, this is not the case, and embedded " characters in arguments for external programs must additionally, manually be \-escaped in order to be passed through properly.

# Broken behavior up to PS v7.2.x

PS> cmd /c echo '{ "foo": "bar" }'
"{ "foo": "bar" }"  # !! Embedded " aren't escaped.

PS> choice.exe /d Y /t 0 /m '{ "foo": "bar" }'
{ foo: bar } [Y,N]?Y  # !! When parsed by an executable, 
                      # !! embedded " are effectively LOST.

# Manual escaping required.
PS> choice.exe /d Y /t 0 /m '{ \"foo\": \"bar\" }'
{ "foo": "bar" } [Y,N]?Y  # OK

This bug has existed since v1, and has never been fixed so as to avoid breaking existing workarounds.


[1] Inside PowerShell, in "..." strings only, you may also use "" to escape an embedded ", as an alternative to `"

Nate Anderson
  • 18,334
  • 18
  • 100
  • 135
mklement0
  • 382,024
  • 64
  • 607
  • 775
7

The backtick ` is used as the escape character in Powershell. That is, escaping quotes, tabs and whatnot. Unlike in many other environments, Powershell's newline is `n, not \n. This has the benefit of simplifying paths, since those use backslash in Windows.

As for a practical example, in many programming languages one needs to escape the backslashes in paths. If you have an application located at

c:\program files\newApplication\myApp.exe

Its path must be written as

c:\\program files\\newApplication\\myApp.exe

The double-backslash notation means that there is actaully a backslash, not a metacharacter such as tab or newline. Note that the path contains \newApplication. Now, \n usually means a newline, but it clearly isn't the case. The file does not reside in

c:\program files\
ewApplication\myApp.exe

after all, doesn't it?

The escaping is not needed in Powershell, as the backslash doesn't have special meaning by itself. When Powershell sees c:\program files\newApplication\myApp.exe, it doesn't assign any special meaning to the forementioned \n part, it is just a string literal.

The backslash \ is used as the escape character in regular expressions and to signify metacharacters. That is, to match a literal * in regex, it must be escaped, lest it means the Kleene star (zero or more matches).

vonPryz
  • 22,996
  • 7
  • 54
  • 65
  • But it was necessary in the answer to this other topic of mine, and it is not a case among those you have listed: https://stackoverflow.com/questions/69827746/powershell-removes-multiple-consecutive-whitespaces-when-i-pass-arguments-to-a-n – Mario Palumbo Nov 04 '21 at 10:18
  • 1
    That's because the `\"` escapes are used to pass values to the wscript VBScript interpreter via invoking a new process. – vonPryz Nov 04 '21 at 10:25
  • But wscript doesn't require \ backslashes when passing parameters, neither calling it directly from PowerShell nor from cmd. Can you explain yourself better? – Mario Palumbo Nov 04 '21 at 11:10
  • 1
    @MarioPalumbo This is because most external programs including PowerShell.exe rely on the CommandLineToArgvW Windows API function to process command line arguments. That requires the `\"` syntax. So when calling an executable from PowerShell, you have to consider the PowerShell layer of escaping (so that PowerShell parses correctly before calling the program) and the called program's required escaping. – AdminOfThings Nov 04 '21 at 12:30