Bash: quoting and expansions

The order of shell expansions, the three kinds of quoting, word splitting, the ${v:-d}, ${v%m} and ${v##m} forms and the here-document: predicting the arguments a command receives.

  • 28 cards
  • 5 topics
  • Free

The outline, topic by topic

Each topic is weighted the way the exam weighs it.

  1. Concepts
  2. Questions
  3. Sort and link
  4. Scenarios
  5. Understand

A few cards from the deck

  • Expansion: what is it?

    Show the answer

    A transformation the shell applies to the command line before starting the program: braces, tilde, variables, commands, arithmetic, word splitting, wildcards.

    The program never sees * or $HOME: it receives the result. It is not ls that replaces *.txt, it is the shell, before calling ls.

  • What does this script print?

    ```bash
    f="mon rapport.txt"
    set -- $f "$f"
    echo $#
    `

    • 3
    • 2
    • 1
    • 4
    Show the answer

    3

    $f unquoted is split into two words (mon and rapport.txt), "$f" makes just one: 2 + 1 = 3 arguments.

  • Among the expansions, the shell handles the … first, then the tilde and variables, next …, and finally the wildcards.

    Show the answer

    Among the expansions, the shell handles the braces first, then the tilde and variables, next word splitting, and finally the wildcards.

    echo {a,b}{1,2} gives a1 a2 b1 b2: braces are expanded before everything else, even before variables. Wildcards come last, on the words already split.

  • Quoting: what is it?

    Show the answer

    A mark that strips a character of its special meaning for the shell: single quotes, double quotes or a backslash.

    Single quotes prevent every expansion; double quotes let $ and \ through; the backslash protects only the next character.

  • A cleanup script runs rm $fichier with fichier="mon fichier" and prints rm: cannot remove 'mon': No such file or directory then rm: cannot remove 'fichier': No such file or directory. Which fix is right?

    • rm '$fichier'
    • rm -f $fichier
    • rm "$fichier"
    • rm ${fichier}
    Show the answer

    rm "$fichier"

    Double quotes keep the variable's content as a single argument. Single quotes would prevent expansion (rm would receive the text $fichier), -f only silences the errors, and braces protect nothing from splitting.