I'm trying to solve a very mundane problem. I want PS1 to change depending upon the previous command executed. Whether success or failure isn't the issue here. I want PS1 to include \w
, but only if the last command entered was cd
. What I have at the moment is:
if [[ !:0 == "cd" ]]
then
PS1='(\w)[jobs: \j] > '
else
PS1='[jobs: \j] > '
The output will always be the shorter one, regardless of the last command.
I feel like I'm making a simple mistake somewhere, and this also seems mundane enough that I can't find anything related through Google.
CodePudding user response:
Put this in .bashrc
:
PROMPT_COMMAND='
if [[ "$NEWPWD" != "$PWD" ]]; then
PS1="(\w)[jobs: \j] > "
NEWPWD=$PWD
else
PS1="[jobs: \j] > "
fi'
You can use whichever name you want for $NEWPWD
It's simple, it works, and is not prone to errors.
CodePudding user response:
The Csh-style !:0
history expansion is an interactive feature. You can use the command history -p "!:0"
to execute it in a script context, though (even when you have set H
, like most sane people have); but executing it inside PROMPT_COMMAND
or the prompt itself is highly unwieldy. (When I tried, it would show me the penultimate command, or something from within the PROMPT_COMMAND
scriptlet itself.)
Borrowing from https://stackoverflow.com/a/6110446/874188 (currently the accepted answer to Echoing the last command run in Bash?) I would go with
trap 'prompt_previous_command=$prompt_this_command; prompt_this_command=$BASH_COMMAND' DEBUG
PS1='$([[ ${prompt_previous_command%%\ *} == "cd" ]] && echo "(${PWD/$HOME/~})")[jobs: \j] \> '
It is unfortunate that echo "\\w"
doesn't produce the expanded value in this context; ${PWD/$HOME/~}
is a reasonable approximation, although there are corner cases where it gets it wrong.
... Perhaps a less confusing approach is to set the value in the trap already:
trap 'prompt_previous_command=$prompt_this_command
prompt_this_command=$BASH_COMMAND
[[ "${prompt_previous_command%%\ *}" == "cd" ]] &&
prompt_cwd="(\\w)" || prompt_cwd=""
PS1="$prompt_cwd[jobs: \\j] \\> "' DEBUG
Many Bash add-ons want to hook into your PROMPT_COMMAND
and might sabotage any attempt to reserve it for youself; of course, this approach has a similar problem if you have something else in your system which relies on the DEBUG
trap for something.
To make this work for pushd
/ popd
and aliases etc too, here's an adaptation of Dan's excellent answer:
trap 'case ${prompt_prev_pwd-$PWD} in
"$PWD") PS1="[jobs \\j] > ";;
*) PS1="(\\w)[jobs: \\j] > ";;
esac
prompt_prev_pwd=$PWD' DEBUG
CodePudding user response:
On approach is to create a function and parse history
. The PROMPT_COMMAND
is also needed.
Put the code below in your ~/.bashrc
file or put it in another file, just make sure you source that file from ~/.bashrc
is_cd(){
set -- $(history 1)
if [[ $2 == "cd" ]]; then
echo cd_is_the_last_command
else
echo no_cd
fi
}
if [[ $PROMPT_COMMAND != *is_cd* ]]; then
PROMPT_COMMAND="is_cd"
fi
Change the lines with
echo
's with the actual command you want to execute.Source
~/.bashrc
after you have edited it.This assumes that the output of your history has the numeric number first and command as the second column.