I have a shell script that runs the same command in several directories (fgit). For each directory, I would like it to show the current prompt + the command which will be run there. How do I get the string that corresponds to the decoded (expanded) PS1
? For example, my default PS1 is
${debian_chroot:+($debian_chroot)}\[\e[1;32m\]\u\[\e[0m\]@\[\e[1;32m\]\h\[\e[0m\]:\[\e[1;34m\]\w\[\e[0m\]$(__git_ps1 ' (%s)')$
and I'd like to echo the resulting prompt username@hostname:/path$
, preferably (but not necessarily) with the nice colors. A cursory look at the Bash manual didn't reveal any definite answer, and echo -e $PS1
only evaluates the colors.
Since Bash 4.4 you can use the @P
expansion:
First I put your prompt string in a variable myprompt
using read -r
and a quoted here-doc:
read -r myprompt <<'EOF'
${debian_chroot:+($debian_chroot)}\[\e[1;32m\]\u\[\e[0m\]@\[\e[1;32m\]\h\[\e[0m\]:\[\e[1;34m\]\w\[\e[0m\]$(__git_ps1 ' (%s)')$
EOF
To print the prompt (as it would be interpreted if it were PS1
), use the expansion ${myprompt@P}
:
$ printf '%s\n' "${myprompt@P}"
gniourf@rainbow:~$
$
(In fact there are some \001
and \002
characters, coming from \[
and \]
that you can't see in here, but you can see them if you try to edit this post; you'll also see them in your terminal if you type the commands).
To get rid of these, the trick sent by Dennis Williamson on the bash mailing list is to use read -e -p
so that these characters get interpreted by the readline library:
read -e -p "${myprompt@P}"
This will prompt the user, with the myprompt
correctly interpreted.
To this post, Greg Wooledge answered that you might as well just strip the \001
and \002
from the string. This can be achieved like so:
myprompt=${myprompt@P}
printf '%s\n' "${myprompt//[$'\001'$'\002']}"
To this post, Chet Ramey answered that you could also turn off line editing altogether with set +o emacs +o vi
. So this will do too:
( set +o emacs +o vi; printf '%s\n' "${myprompt@P}" )