mkdir $2 || echo “I can’t create directory $2” && exit 8
Hi everyone, this is my first post here, so be kind.
I am making a script right now and this line troubles me.
The exit 8 should happen only if the directory $2 cannot be created. After running the script and successfully creating that directory, it still exits on 8.
Am I missing something? I thought the command after ” || ” happens only if you get a false on the left side.
I am new to the Linux world, and as a guy with a little to medium C experience I am confused, help! (using ubuntu, bash, btw)
Advertisement
Answer
As @fernand0 suggested, the problem is the precedence of the ||
and &&
operators. You want it to run something like mkdir || ( echo && exit )
— that is, run the echo && exit
part if mkdir
fails. But what it’s actually doing is running something like ( mkdir || echo ) && exit
— that is, it runs the exit
part if either the mkdir
OR echo
command succeeds. echo
will almost always succeed, so it’ll almost always exit.
So, you need to explicitly group the commands, to override this precedence. But don’t use ( )
, because that runs its contents in a subshell, and exit
will just exit the subshell, not the main script; you can use { }
instead, or use an explicit if
block. Also, you don’t actually want echo && exit
, because that runs exit
only if the echo
command succeeds. echo
almost always succeeds, but in the rare case that it fails I’m pretty sure you want the script to exit anyway.
When I need to do something like this in a script, I usually use this idiom:
mkdir "$2" || { echo "I can't create directory $2" >&2 exit 8 }
(Note: as @CharlesDuffy suggested, I added double-quotes around $2
— double-quoting variable references is almost always a good idea in case they contain any spaces, wildcards, etc. I also sent the error message to standard error (>&2
) instead of standard output, which is also generally a better way to do things.)
If you want to be terser, you can put it all on one line:
mkdir "$2" || { echo "I can't create directory $2" >&2; exit 8; }
Note that the final ;
(or a line break) is required before the }
, or the shell thinks }
is just an argument to exit
. You could also go the other way and use an explicit if
block:
if ! mkdir "$2"; then echo "I can't create directory $2" >&2 exit 8 fi
This option is less clever and concise, but that’s a good thing — clever and concise is exactly what caused this problem in the first place; clear and unambiguous is much better for code.