• United States
Unix Dweeb

Demystifying &&, ||, and ! on Linux

Apr 11, 20224 mins

&&, || and ! operators can run tests and take actions based on the test results, but they can be a little tricky until you understand the logic.

man looking up linux code command for user assessment by electravk getty images
Credit: electravk / Getty Images

The &&, ||, and ! operators allow you to run a lot of useful commands on Linux, but you first need to get used to syntax that is a little trickier than the if-then-else command you might normally use.

To get started, I should explain that one thing the command examples in this post have in common is the use of something that I might call a shorthand “if” test. Here’s an example:

$ [ -f donuts ]
$ echo %?

The -f donuts command asks if there is a file (-f) named “donuts”. Unless we display the return code afterwards with “echo $?”, the result of the test is not displayed. In this case, it’s false (i.e., not zero), so we know the file doesn’t exist. No donuts for us!

To compose a similar but opposite test, we could ask if no donuts file exists. That test would look like this:

$ [ ! -f donuts ]
$ echo $?

That time, the result is true (0). No donuts again. However, this isn’t how these commands are generally used. Instead, && or || operators are added to the end to run some command based on the results of the test that is run. For example, if there is no donuts file, you might want to lodge a complaint like this:

$ [ ! -f donuts ] && echo “We need donuts!”

The key is to understanding this command is that && is an “AND” operator while || is an “OR” operator. If you run a command like the one shown above, both sides of the command — the test and the resulting command — will run if there is no file named “donuts”. The command basically says that “if a file named donuts does not exist, display the text using the echo command. Using &&, whenever the result of the test using is true, the command on the right side of the && is run. If the result is false, the command ends.

This command says “if there is a directory named mydir”, display a listing:

$ [ -d mydir ] && ls -ld mydir
drwxr-xr-x. 2 shs shs 4096 Apr 11 11:46 mydir

In this next example, we test whether a directory does not exist. If it doesn’t, the mkdir command will create one. The second command shown below verifies that the directory was created. If the directory exists already, the command will yield a failure status and the mkdir command will not be run.

$ [ ! -d newdir ] && mkdir newdir
$ ls -ld newdir
drwxr-xr-x. 2 shs shs 4096 Apr 11 11:54 newdir

The opposite is true when you use ||. If the first part of the command succeeds (yields “true”), the second part is never run.

For && operators, the following logic is implemented:

If SUCCESS then RUN 2nd command
If FAIL    then END

If you run a command using ||, the second part of the command will only run if the first fails. If the first part is successful, the command is finished. In other words, the overall command is successful if either part works.

For || operators, the following logic is implemented:

If FAIL    then RUN 2nd command

In this next example, we ask if there is a directory named “scripts”. If there isn’t (i.e., the test result is “false”), the second part of the command is run and the mkdir command creates it. If there is a scripts directory, the command ends and the mkdir command is not run.

$ [ -d scripts ] || mkdir scripts
$ ls -ld scripts
drwxr-xr-x. 2 shs shs 4096 Apr 11 12:16 scripts


Even though && and || behave differently, you can use either of the operators to get the same result. The examples below illustrate this.

Each of the commands below will create a file named notes if one doesn’t exist and do nothing if it does.

$ [ ! -f notes ] && touch notes
$ [ -f notes ] || touch notes

Similarly, each of the two commands below creates a scripts directory if one doesn’t already exist and otherwise make no changes.

$ [ ! -d scripts ] && mkdir scripts
$ [ -d scripts ] || mkdir scripts

While using && and || may seem a bit tricky, a little practice and some handy example commands can really pay off.

Unix Dweeb

Sandra Henry-Stocker has been administering Unix systems for more than 30 years. She describes herself as "USL" (Unix as a second language) but remembers enough English to write books and buy groceries. She lives in the mountains in Virginia where, when not working with or writing about Unix, she's chasing the bears away from her bird feeders.

The opinions expressed in this blog are those of Sandra Henry-Stocker and do not necessarily represent those of IDG Communications, Inc., its parent, subsidiary or affiliated companies.

More from this author