I would like to chain the OR and AND commands so that I print the contents of a directory to stdout if the directory exists, or in the case that it does not, print a message to stdout saying that the directory "$MY_DIR" is being created and then create it.
I have the following code.
ls "$MY_DIR" || echo "Creating $MY_DIR" && mkdir -p "$MY_DIR"
Is this the correct and canonical way to do this? Will mkdir
always run since echo
will return 0
return status, even in the case that ls
does return?
The most relevant question I have located so far is this one which does not eliminate my doubts.
CodePudding user response:
I would not do what you are doing that way in any case. You should group your commands for clarity if for no other reason.
ls "$MY_DIR" || {
echo "Creating $MY_DIR"
mkdir -p "$MY_DIR"
}
This has several advantages: your intent is more clearly expressed, there is less ambiguity between what the human thinks will happen and what the computer will do, and it stops relying on the exit code from echo
that you were not really interested in to begin with. Even if your original version worked entirely correctly it was more vulnerable to later, naïve modification.
A oneliner form is of course possible, if less readable:
ls "$MY_DIR" || { echo "Creating $MY_DIR"; mkdir -p "$MY_DIR"; }
As for your original method, consider this:
If the ls
command fails:
false || true && echo mkdir # prints mkdir
But if the ls
command succeeds
true || true && echo mkdir # also prints mkdir
Whereas
true || { true; echo mkdir; } # does not print
false || { true; echo mkdir; } # prints mkdir
It gets worse: I am not entirely clear whether ls
will set an unsuccessful return code if the file/directory does not exist. It's certainly true that GNU ls
does this, and it may be common, but the standard doesn't seem to say what constitutes success or failure, so implementations may well disagree.
CodePudding user response:
Why does it have to be chaining, with all the potential problems that might bring? Why not express your intentions clearly?
Also, UPPERCASE is usually reserved for environment variables.
# -d checks for directory specifically, use -e for existence.
# Thanks to @sorpigal for pointing it out.
if [[ -d $my_dir ]]
then
ls "$my_dir"
else
echo "Creating $my_dir"
mkdir -p "$my_dir"
fi
Or, if it has to be one line...
if [[ -d $my_dir ]]; then ls "$my_dir"; else echo "Creating $my_dir"; mkdir -p "$my_dir"; fi