292

Sometimes when making conditionals, I need the code to do nothing, e.g., here, I want Bash to do nothing when $a is greater than "10", print "1" if $a is less than "5", otherwise, print "2":

if [ "$a" -ge 10 ]
then
elif [ "$a" -le 5 ]
then
    echo "1"
else
    echo "2"
fi

This makes an error though. Is there a command which will do nothing and also not slow down my script?

3
  • echo $[a<=5?1:2] a brief ternary does it, ignoring any test for a>=10
    – roblogic
    Commented Jul 24, 2023 at 12:51
  • @roblogic, why would you use ancient/deprecated/nonstandard ksh syntax when there are standardized options ($((a <= 5 ? 1 : 2))) available? Commented Mar 12 at 16:52
  • $[] is supported in bash, but yes $(()) is probably better. I like to be brief.
    – roblogic
    Commented Mar 20 at 2:52

5 Answers 5

544

The no-op command in shell is : (colon).

if [ "$a" -ge 10 ]
then
    :
elif [ "$a" -le 5 ]
then
    echo "1"
else
    echo "2"
fi

From the bash manual:

: (a colon)
Do nothing beyond expanding arguments and performing redirections. The return status is zero.

10
  • 5
    @SaintHax No, it doesn't run true. It's built into the shell, and does nothing.
    – Barmar
    Commented May 26, 2017 at 19:29
  • 1
    it is shell built in (you are correct), it returns true (status 0) just like true does, and it is more difficult to read. Bash is a DevOps language, and if : is written by someone on my team, I'd have them change it.
    – SaintHax
    Commented May 29, 2017 at 19:51
  • 6
    @SaintHax If someone used true in a non-conditional context, I'd have them change it. if true is fine, then true seems wrong.
    – Barmar
    Commented May 29, 2017 at 21:29
  • 5
    Of course, you can simply rewrite the code to use if ! condition; then do something; fi instead of if condition; then :; else do something; fi.
    – Barmar
    Commented May 29, 2017 at 21:30
  • 2
    E.g. while ! ping -c 1 hostname; do : done to wait for ping to succeed. @kingsjester
    – Barmar
    Commented Nov 18, 2022 at 15:27
64

You can probably just use the true command:

if [ "$a" -ge 10 ]; then
    true
elif [ "$a" -le 5 ]; then
    echo "1"
else
    echo "2"
fi

An alternative, in your example case (but not necessarily everywhere) is to re-order your if/else:

if [ "$a" -le 5 ]; then
    echo "1"
elif [ "$a" -lt 10 ]; then
    echo "2"
fi
4
  • 8
    If you don't test the result both true and false are effectively no-ops as far as the script is concerned, but in principle they could fork in some shells that accept this syntax so perhaps : is better. Commented Jul 11, 2013 at 1:31
  • 3
    The question is tagged bash. In bash, true and false are built-ins. For older shells, true, false, and even : might be external commands (though you'd probably see the latter only in very old shells). Commented Jan 12, 2014 at 4:37
  • 8
    I prefer : simply because it is more explicit what the intent is Commented Sep 19, 2014 at 21:12
  • 1
    The result false may not be a no-op, because if set -e is used (exit on non-zero) then false will cause the script to exit immediately. true is a better no-op. : is a real no-op, but I have to agree that it is unreadable and I've been programming bash for 30 years and I didn't know about it... Commented Dec 8, 2021 at 18:48
12

Although I'm not answering the original question concering the no-op command, many (if not most) problems when one may think "in this branch I have to do nothing" can be bypassed by simply restructuring the logic so that this branch won't occur.

I try to give a general rule by using the OPs example

do nothing when $a is greater than "10", print "1" if $a is less than "5", otherwise, print "2"

we have to avoid a branch where $a gets more than 10, so $a < 10 as a general condition can be applied to every other, following condition.

In general terms, when you say do nothing when X, then rephrase it as avoid a branch where X. Usually you can make the avoidance happen by simply negating X and applying it to all other conditions.

So the OPs example with the rule applied may be restructured as:

if [ "$a" -lt 10 ] && [ "$a" -le 5 ]
then
    echo "1"
elif [ "$a" -lt 10 ]
then
    echo "2"
fi

Just a variation of the above, enclosing everything in the $a < 10 condition:

if [ "$a" -lt 10 ]
then
    if [ "$a" -le 5 ]
    then
        echo "1"
    else
        echo "2"
    fi
fi

(For this specific example @Flimzys restructuring is certainly better, but I wanted to give a general rule for all the people searching how to do nothing.)

2
  • 7
    One reason someone might want to have a no-op is when initially structuring the code with the idea that one will add the "add something here later" without having inadvertent side effects. E.g. if one is putting an if-then-else-fi in a .bashrc, if you put echo "put stuff here" it'll break some of the non-login uses (e.g. scp gets broken), and only whitespace/comments causes a runtime error.
    – Aphoid
    Commented Jan 2, 2018 at 16:38
  • 1
    Also, personally, I prefer to write code that is more "human friendly". It's often possible to restructure code to be more concise or even efficient. But when that's not critical, I prefer my code to be more readable for whichever developer comes along afterwards. (I also like commenting my code.)
    – osullic
    Commented Jan 6, 2021 at 10:08
1

It looks like that there is no other way than writing your own nop as a function. : does not the intended job, as it affects the exit status; maybe you'll find a builtin in the manual that does not change the exit status, but I've failed to exhibit such a one. You may say:

nop() { return; } # may return $?
bad() { return 42; }

bad; nop; echo $? # "nop" does nothing and keeps status; echo echoes 42
bad; :  ; echo $? # ":" does nothing but changes status; echo echoes 0
0

instead of :, true, false I use

echo -n ""

It avoid empty line in terminal

You could also do it more concisely as:

echo -n
1
  • echo -n is listed in the POSIX specification as explicitly undefined behavior (see the APPLICATION USAGE section of pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html spelling this out), and even if you 100% know your shell is bash, it still can change behavior on runtime flags (see shopt -s xpg_echo and how its behavior meshes with set -o posix -- moreover, both those flags can be set by environment variables even if your code never actually runs them). Commented Mar 12 at 16:54

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