22

Why when I enter this command the prompt changes to my directory?

PS1='$(pwd)'

I am using single quotes, which means no interpolation , a.k.a echo '$(pwd)' ——→ $(pwd)

Furthermore, say that we clarified why this works... why is it functioning differently from PS1=$(pwd) ? (no quotes at all)

By different I mean that if I use the quotes then the prompt will keep changing to my current directory as I navigate through the terminal. But if I don't use quotes, then the prompt will always remain the directory that I was in when I first entered the command PS1=$(pwd)

why?

3 Answers3

31

When you simply assign a value to a variable, the $(...) expression is evaluated unless it is enclosed in single quotes (or backslash-escaped). To understand, try and compare these two:

A=$(pwd)
echo "$A"
B='$(pwd)'
echo "$B"

The value of A immediately becomes the string /home/yourusername and obviously it's not remembered where this string comes from, it stays the same even if you change directory. The value of B, however, becomes the literal string $(pwd) without getting interpreted.

Now, in the value of PS1 something special happens: whenever the prompt is printed, certain special constructs are interpreted, e.g. the command substitution $(...) is performed exactly the way it happened above at the assignment to the A variable. Obviously if your PS1 contains the literal string of your home directory (as above with A) then there's no way it could change. But if it contains the string $(pwd) (as above with B) then it is evaluated whenever the prompt is printed and hence your actual directory is displayed.

egmont
  • 5,866
15

In both bash and zsh, the value of PS1 is not used as a prompt as-is, it undergoes some expansions. The rules differ for the two shells, but in both cases, one of the step is to perform “dollar” expansions (variable substitution, command substitutions, arithmetic evaluation) with the same syntax as in normal shell syntax ($VARIABLE, ${VARIABLE}, $(COMMAND) or `COMMAND`, $((EXPRESSION)), $[EXPRESSION]) .

  • In bash, dollar expansion is turned on by default, but can be turned off with shopt -u promptvars.
  • In zsh, dollar expansion is off by default, but many people (and most configuration frameworks you'll find on the web) turn it on with setopt prompt_subst.

With dollar expansion in the prompt turned on, PS1='$(pwd)' sets PS1 to the 6-character value $(pwd) and thus causes $(pwd) to be substituted, and therefore the pwd command to be executed, each time the shell displays a new prompt. On the other hand, PS1=$(pwd) sets PS1 to whatever is the shell's current working directory at the time. If you had dollar expansion turned off then PS1='$(pwd)' would cause the prompt to be the literal string $(pwd).

Note that there are more convenient ways to get the working directory in the prompt:

  • In bash, with a backslash escape such as \w, which abbreviates your home directory to ~ and may be trimmed by setting PROMPT_DIRTRIM.
  • In zsh, with a percent escape such as %/ or %~ (%/ is the same as $PWD, %~ abbreviates home directories), which can have a trimming setting.
  • In either shell (and any other Bourne-style shell), $PWD is equivalent to $(pwd): you don't need to run a subprocess to get the current working directory.
7

Because without the quotes, the $(pwd) is evaluated when PS1 is set. With the quotes, the evaluation of $(pwd) is postponed until the prompt is displayed.

Without the quotes, PS1 is set to the current directory at the time PS1 is set. With the single quotes PS1 is set to $(pwd), which means it will evaluate and print the current directory each time the prompt is displayed.

h2ohcl
  • 38