Home > Enterprise >  Expand Last Command in Conditional Statement
Expand Last Command in Conditional Statement

Time:11-10

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.

  •  Tags:  
  • bash
  • Related