2

In ksh on an old Solaris box I used:

export PS1="$PWD $"

to set the prompt to the current directory. It works great until you cd elsewhere, then you see that it's not evaluating PWD each time. I notice that it's fixed by instead setting PS1 like this:

export PS1="\$PWD $"

Just curious what it's called, how it works, other applications etc. (It's one of those things that's quite resistant to Googling.)

  • If you do export PS1='$PWD $' (single, not double, quotes), does that work as well? – Mark Plotnick Oct 16 '14 at 16:30
  • @MarkPlotnick Yes, doing that means I don't need the \. – user13757 Oct 16 '14 at 16:37
  • @Poldie: What MarkPlotnick was trying to say is to try it without the `. You'll discover that it doesn't work as soon as you cd` to another directory. Now think what $PWD means and consider why the prompt will always show the same directory regardless of where you're at. – slebetman Oct 17 '14 at 2:05
  • @slebetman I think he was quite clearly saying to try with single quotes and without the \, otherwise he would have mentioned the other character (which this site doesn't display properly). – user13757 Oct 17 '14 at 8:03
  • I wanted to verify that Poldie's old shell would not do parameter expansion within single quotes. It behaved as expected. – Mark Plotnick Oct 17 '14 at 13:51
9

A few pieces of documentation will help to explain this.

From the POSIX standards document for the shell:

The following variables shall affect the execution of the shell:
PS1: Each time an interactive shell is ready to read a command, the value of this variable shall be subjected to parameter expansion and written to standard error.
...
Single-Quotes
Enclosing characters in single-quotes shall preserve the literal value of each character within the single-quotes.
...
Double-Quotes
Enclosing characters in double-quotes shall preserve the literal value of all characters within the double-quotes, with the exception of
$: The dollar sign shall retain its special meaning introducing parameter expansion
...
Escape Character (Backslash)
A backslash that is not quoted shall preserve the literal value of the following character.

So the value of PS1 is subject to parameter expansion, and this is what you want, so that $PWD will be evaluated every time you get a prompt. This means there needs to be an actual $PWD string in the value of PS1. But,

export PS1="$PWD $ "

will put the value of PWD at the time the export statement is run into PS1. PS1 will be something like /home/poldie $, and it'll never change after that. You don't want that.

export PS1="\$PWD $ "

The backslash will quote the $, so that PS1 contains the literal string $PWD $. You want this.

export PS1='$PWD $ '

will do the same thing. Parameters are not expanded when surrounded by single quotes.

3

The \ character escapes the following (special) character. In this case, it escapes the $, which we usually use to dereference a variable. When the shell evaluates a variable assignment, it first expands the right-hand-side of the expression. Without the \ before $PWD, the shell expands $PWD and assigns the result to PS1.

However, with the \, the shell treats $PWD as a literal string, and assigns it as-is to PS1, so that PS1 contains the string $PWD, and not the expanded value of the variable $PWD. When the shell is about to display the prompt, it once again carries out variable expansion, and this time, because $PS1 contains $PWD, without the \, the shell successfully expands it to the current directory.

The same approach can be used to create dynamic variable names in shell scripts (the NetBSD rcNG system uses this quite widely, especially in scripts controlling network interfaces, where the number of network adapter designations in NetBSD and FreeBSD make it impractical to explicitly code for each one).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy