3

I am using this piece of code directly in the command prompt (PS1), and it tells me whether the previous command executed correctly.

PS1="\`if [ \$? = 0 ]; then echo -e \"\e[1;32m[⚡️ ]\"\e[0m; else echo -e \"\e[1;31m[💥 ]\"\e[0m; fi\`-[\u@\h: \w]"

I don't like the backticks notation. Is there a way to execute it without using ``?

Also, is there a reason this would interfere with the results from a another script? I've exposed a function that I called in the command prompt, but this piece messes up the results. The function gets called only once when PS1 is exported and not every time that the command prompt is loaded.

Update 1: So I tried the plain "$()" but it didn't work. And, now I am more puzzled because if add a backslash to it works – "\$()". Why is this? Does anyone know of this? Does "$" need to be escaped?

The original works:

export PS1="[\`if [ \$? = 0 ]; then echo -e \"\e[1;32m[⚡️ ]\"\e[0m; else echo -e \"\e[1;31m[💥 ]\"\e[0m; fi\`]-[\u@\h: \w] \$ "

Result:

[⚡️ ]-[rordev@Luiss-MBP: ~/Development/test] $

This doesn't work:

export PS1="[$(if [ $? = 0 ]; then echo -e \e[1;32m[⚡️ ]\e[0m; else echo -e \e[1;31m[💥 ]\e[0m; fi)]-[\u@\h: \w] \$ "

Result:

-bash: 32m[⚡️: command not found
[e[1]-[rordev@Luiss-MBP: ~/Development/test] $

But this works. Why? and why is the backslash needed before$()?

export PS1="\$(if [ \$? = 0 ]; then echo -e \"\e[1;32m[⚡️ ]\"\e[0m; else echo -e \"\e[1;31m[💥 ]\"\e[0m; fi)-[\u@\h: \w] \$ "

Result:

[⚡️ ]-[rordev@Luiss-MBP: ~/Development/test] $ 

Update 2: I tried the suggestions and it works. Well, sort of.

I have to call the conditional first and the function last.

PS1="\$(if [ \$? = 0]; then ...; else ...; fi)-[\u@\h: \w\$(myFunction)]"

But it doesn't work the other way.

PS1="[\u@\h: \w\$(myFunction)]-\$(if [ \$? = 0]; then ...; else ...; fi)"

The function is called and the results are displayed, but the conditional does not seem to be executing, or rather the status code returned seems to always be 0. So it always shows the first part of the conditional.

Any ideas about that? I suspect that it has something to do with the order in which the command substitutions are executed.

8
PS1="\`if [ \$? = 0 ]; then ... fi\`

Update: So I tried the plain "$()" but it didn't work. And, now I am more puzzled because if add a forward slash to it works - "\$()".

The \ is a backslash, not a forward slash.

You need to escape the $ here for the same reason you escaped the backticks in the first snippet: because otherwise the command substitution is expanded immediately, when setting PS1, and not when PS1 is used to produce a prompt.

You're better off using single quotes around the assignment, they'll prevent expanding variables and command substitutions for the whole string.

PS1='$(if [ $? != 0 ]; then echo -e "\[\e[1;31m\][boom]\[\e[0m\] "; fi)\u@\h \w\$ '

Note, that you need to wrap the escape codes within \[ ... \] to tell bash that they don't print, and that it shouldn't take them into account when calculating the width of the prompt (mentioned in passing in the manual). (I don't know if Bash can correctly deal with the graphic characters you used, and I can't test.)

  • 2
    proper escape codes for ANSI colors do not need a closing square backet ] – luis.madrigal Jun 13 '17 at 5:55
  • @luis.madrigal, As terminal control sequences, no, they don't contain a ]. To tell the shell the control sequence doesn't produce visible characters, yes, you do need the brackets, and yes you do need to close them. Read the last paragraph again. – ilkkachu Jun 13 '17 at 6:02
  • Take 2: A proper escape codes for ANSI colors does not need a closing square backet "]". The open square bracket "[" is the only one needed and it is called the Control Sequence Introducer or CSI for short and tells the interpreter to accept the characters that follow as part of the escape sequence. The m is the closing character in the sequence and it is called the final character. – luis.madrigal Jun 13 '17 at 6:03
  • @luis.madrigal, yes, I know. The control sequence \e[1;31m doesn't contain a closing bracket. – ilkkachu Jun 13 '17 at 6:07
  • I didn't see your comment. I was in the middle of writing the my second comment. Thanks for the response it was very helpful. – luis.madrigal Jun 13 '17 at 6:25
-1

I don't like the backticks notation, is there a way to execute it without using ``?

The function is called and the results are displayed, but the conditional does not seem to be executing, or rather the status code returned seems to always be 0. So it always shows the first part of the conditional.

Any ideas about that? I suspect that it has something to do with the order in which the command substitutions are executed.

  • My suggestion is to transfer all the logic to the PROMPT_COMMAND variable to make things clear.
    As stated at the Bash Prompt Howto The contents of this variable are executed as a regular Bash command just before Bash displays a prompt, which means, before the call to the $PS1 variable.

For example:

    # Notice that we need to save the exit status to preserve it
    # and avoid what you are reporting(always returning 0)
    choose_icon() {
        RET=$?; # Save the exit status
        # Using short circuit evaluation to make statement shorter
        [[ $RET != 0 ]] && ISTATUS=💥 || ISTATUS=⚡️
        return "$RET" # Return the original exit status to your shell
    }
    PROMPT_COMMAND="choose_icon" # or/and any other function/command
    PS1='[$ISTATUS]\u@\h \w\$ '
  • 1
    the command substitution runs in a subshell, and you don't need to export variables for them to be seen by one. – ilkkachu Jun 13 '17 at 5:55

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.