What is the significance of backslashes, backticks, and carets in various shells
Asked Answered
A

2

3

I am following https://docs.docker.com/get-started/06_bind_mounts/#start-a-dev-mode-container on a Windows PC and am stuck here:

Run the following command. We’ll explain what’s going on afterwards:

 docker run -dp 3000:3000 \
     -w /app -v "$(pwd):/app" \
     node:12-alpine \
     sh -c "yarn install && yarn run dev"

If you are using PowerShell then use this command:

 docker run -dp 3000:3000 `
     -w /app -v "$(pwd):/app" `
     node:12-alpine `
     sh -c "yarn install && yarn run dev"

When using Command Prompt, I get errors (tried multiple variations as shown below), and when using PowerShell, I don't appear to get errors but am not running anything as showed when executing docker ps. Note that I would rather use Command Prompt and not PowerShell as I could use Linux commands with ComandPrompt on my PC.

What is the significance of backslashes when using Dockers with Command Prompt (and tick marks with PowerShell for that matter)?

I have since found that docker run -dp 3000:3000 -w /app -v "%cd%:/app" node:12-alpine sh -c "yarn install && yarn run dev" works without errors (got rid of backslashes, put on one line, and used %cd% instead of $(pwd)), but would still like to know why using the exact script in the example results in errors.

Using Command Prompt

C:\Users\michael\Documents\Docker\app>docker run -dp 3000:3000 \
docker: invalid reference format.
See 'docker run --help'.

C:\Users\michael\Documents\Docker\app>     -w /app -v "$(pwd):/app" \
'-w' is not recognized as an internal or external command,
operable program or batch file.

C:\Users\michael\Documents\Docker\app>     node:12-alpine \
The filename, directory name, or volume label syntax is incorrect.

C:\Users\michael\Documents\Docker\app>     sh -c "yarn install && yarn run dev"
sh: yarn: command not found

C:\Users\michael\Documents\Docker\app>docker run -dp 3000:3000 \ -w /app -v "$(pwd):/app" \ node:12-alpine \ sh -c "yarn install && yarn run dev"
docker: invalid reference format.
See 'docker run --help'.

C:\Users\michael\Documents\Docker\app>docker run -dp 3000:3000 -w /app -v "$(pwd):/app" node:12-alpine sh -c "yarn install && yarn run dev"
docker: Error response from daemon: create $(pwd): "$(pwd)" includes invalid characters for a local volume name, only "[a-zA-Z0-9][a-zA-Z0-9_.-]" are allowed. If you intended to pass a host directory, use absolute path.
See 'docker run --help'.

C:\Users\michael\Documents\Docker\app>

Using PowerShell

PS C:\Users\michael\Documents\Docker>  docker run -dp 3000:3000 `
>>      -w /app -v "$(pwd):/app" `
>>      node:12-alpine `
>>      sh -c "yarn install && yarn run dev"
849af42e78d4ab09242fdd6c3d03bcf1b6b58de984c4485a441a2e2c88603767
PS C:\Users\michael\Documents\Docker> docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
PS C:\Users\michael\Documents\Docker>
Aircraftman answered 15/8, 2021 at 17:21 Comment(4)
Unclear what you mean by "use Linux commands in command prompt"... But you'll need to look at docker logs to know why the container is actually failing (probably something bad in the yarn process)Estipulate
@OneCricketeer, When installing git, installed tools to allow me to use ls -l instead of dir.Aircraftman
Sounds like you're using "Git Bash", which is not CMD. Basically, I'd consider that deprecated in favor of WSL2 overallEstipulate
@Estipulate Yes I was. Through it might be causing problems (unfortunately it wasn't the culprit) but couldn't remember what it was called until seeing your comment. Will checkout WSL2. ThanksAircraftman
S
10

would still like to know why using the exact script in the example results in errors.

Because the command with the line-ending \ characters is meant for POSIX-compatible shells such as bash, not for cmd.exe

  • POSIX-compatible shells (sh, bash, dash, ksh, zsh):

    • use \ for line-continuation (continuing a command on the following line) and escaping in general.
    • use $varName to reference both environment and shell-only variables.
    • support $(...) for embedding the output from a command (...) in command lines (command substitution).
    • support both double-quoted ("...", interpolating) and single-quoted ('...', verbatim) strings; use '\'' to - in effect - include a ' inside '...'.
      (Additionally, in bash, ksh, and zsh, there are the rarely used ANSI C-quoted strings, $'...', and, in bash and ksh, perhaps even more rarely, localizable strings, $"...").
  • cmd.exe:

    • uses ^ for line-continuation and escaping in general (in unquoted arguments only).
    • uses %varName% to reference environment variables (the only variable type supported).
    • doesn't support command substitutions at all.
    • supports only "..." strings (interpolating).
  • PowerShell:

    • uses ` (the backtick) for line-continuation and escaping in general.
    • uses $env:varName to reference environment variables, $varName to reference shell-only variables.
    • supports $(...), called subexpressions, the equivalent of command substitutions (outside of double-quoted strings, (...) is usually sufficient).
    • supports both double-quoted ("...", interpolating) and single-quoted ('...', verbatim) strings; use '' to embed a ' inside '...'.
    • Note: A common pitfall is that PowerShell has more metacharacters compared to both POSIX-compatible shells and cmd.exe, notably including @ { } , ;, which therefore require individual `-escaping in unquoted arguments or embedding in quoted strings - see this answer.

Potential line-continuation pitfall: in all of the shells discussed, the escape character must be the very last character on the line - not even trailing (intra-line) whitespace is allowed (because the escape character would then apply to it rather than to the newline).

The information above is summarized in the following table:

Feature POSIX shells                     _ cmd.exe                     _ PowerShell                     _
Line-continuation / escape character Backslash (\) Caret (^) Backtick (`)
Double-quoted strings (interpolating)
Single-quoted strings (verbatim)
Get / set environment variables $varName /
export varName=...
%varName% /
set varName=...
$env:varName /
$env:varName = ...
Get / set shell-only variables $varName/
varName=...
❌ (no such variables exist, but you can limit the scope of env. vars. with setlocal) $varName/
$varName = ...
Command substitutions, subexpressions $(...) (...) / $(...), esp. in strings

Note re setting variables with respect to whitespace on either side of the = symbol:

  • In POSIX-like shells, there must not be whitespace around =.
  • In cmd.exe, such whitespace is significant and becomes part of the variable / value name, and is therefore usually to be avoided.
  • In PowerShell, such whitespace is optional - you may use it to enhance readability; any string value to be assigned requires quoting (e.g., $var = 'hi!')

See also:

Subjacent answered 15/8, 2021 at 19:1 Comment(3)
Very comprehensive and high quality answer. Especially helpful given the difficulty to search for information for these types of items. Thank you.Aircraftman
Wow, you did pretty it up! Ignore my part about input command substitutions as I was confused.Aircraftman
Got it, @user1032531. I've added a link to hyperpolyglot.org/shell, which is a comprehensive juxtaposition of these shells, though note that details are missing, esp. with respect to PowerShell.Subjacent
G
3

This is character escaping.

The X Character (\ for Bash, backtick for Powershell and ^ for Windows terminal )are used to remove any specific meanings to the next characters.

When used at the end of a line, this mean that the next character (The newline character) is completely ignored.

This keep the command essentially a one-line command from the point of view of the interpreter, but allow you to break it on multiple lines for better readability.

References

Powershell - About special characters

Escape sequences begin with the backtick character [`], known as the grave accent (ASCII 96), and are case-sensitive. The backtick character can also be referred to as the escape character.

Bash manual

3.1.2.1 Escape Character

A non-quoted backslash \ is the Bash escape character. It preserves the literal value of the next character that follows, with the exception of newline. If a \newline pair appears, and the backslash itself is not quoted, the \newline is treated as a line continuation (that is, it is removed from the input stream and effectively ignored).

How-to: Escape Characters, Delimiters and Quotes at the Windows command line

Escaping CR/LF line endings. The ^ escape character can be used to make long commands more readable by splitting them into multiple lines and escaping the Carriage Return + Line Feed (CR/LF) at the end of a line:

ROBOCOPY \\FileServ1\e$\users ^
\\FileServ2\e$\BackupUsers ^
/COPYALL /B /SEC /MIR ^
/R:0 /W:0 /LOG:MyLogfile.txt /NFL /NDL

[...]

A couple of things to be aware of:

A stray space at the end of a line (after the ^) will break the command, this can be hard to spot unless you have a text editor that displays spaces and tab characters. If you want comment something out with REM, then EVERY line needs to be prefixed with REM. Alternatively if you use a double colon :: as a REM comment, that will still parse the caret at the end of a line, so in the example above changing the first line to :: ROBOCOPY… will comment out the whole multi-line command.

Golly answered 15/8, 2021 at 19:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.