Shell advanced syntax?

I am not an expert of shell scripting, but I can do some simple things. Now, I read a script written by others and I need some help from the experts of this forum.

Please help me to understand what is going on in this cycle:

if [ $COMPILER = "sun" ]; then
[[ -f /sunstudio12/bin/sunf90 ]] && \
      export IMDI_COMPILER=/sunstudio12/bin/sunf90 || \
      { 
      echo "Please specify location!"; exit; 
      }
    [[ -z "$SZIP_ROOT" ]] && SZIP_ROOT=/szip-2.1
elif [ $COMPILER = "intel" ]; then
....

In particular, I do not understand this synax: [[...]] && \ export... ||,
where the || operand is used after the export command. It rise by me the question if the export command return any Boolean value?

Thank you in advance for help!

[[...]] && export... ||,

is one line form of

if [[ ... ]] ; then
export...
else
echo "Please ...
fi

the \ is used for cosmetic reasons : when a line is too long, you can break it by typing <enter> but in order to "desactivate" the <enter> you have to protect it first by a \

so the line

[[...]] && export... || cmd...

can be put one several line to make it readable when commands are too long:

[[...]] && \
export... || \
cmd...
2 Likes

Thank you very much for good answer!

But I would like to point out two things that are still unclear to me:

  1. Actually, I have two ifs or not? I mean when typing
if [[...]]; then
   [[....]]
elif....
  1. Mainly, what is a bit strange for me, is the following:
if [[.....]] ; then
   [[ -f ... ]] && \
      export  ... || \
      { 
      echo ...; exit; 
      }

because I am expecting no return from export command. So, why should I ask like this:

 [[...]] AND export VAR OR...

I think it is equivalent to this:

if [ $COMPILER = "sun" ]; then
  if [[ -f /sunstudio12/bin/sunf90 ]]; then
    export IMDI_COMPILER=/sunstudio12/bin/sunf90
  else
    echo "Please specify location!"
    exit
  fi
  if [[ -z "$SZIP_ROOT" ]]; then
    SZIP_ROOT=/szip-2.1
  fi
elif [ $COMPILER = "intel" ]; then
1 Like

I agree with the dude Scrutinizer :slight_smile:

1 Like

[[ xxx ]] is test [ xxx ], see man test or test in man ksh.

I call this "procedure as logic". Run the expresions and commands connected by && in order and keep going as long as commnads return true). You see this in PERL and C/C++ occasionally. Every command returns a logical value, the state of $?, 0 = true. I prefer, for each step, "if ( !next_command );then print error on next command and exit". It keeps the indentedness under control, separates the steps and reads easily. I call it "Cut them off at the pass!" (prevent complexity by doing simple, important things first, and when they are out of the way, the rest is simpler).

1 Like

Sorry, but this is absolute tosh. A Conditional Expression is not the same as a "test" and they have their own syntax and rules. Admittedly there is some small overlap in the syntax for certain conditions (such as "-f").

1 Like

That's close but not quite correct. The original version's echo executes if the export command fails. This interpretation's does not.

Regards,
Alister

1 Like

Now I agree with Dude Alister ... LoL

1 Like

A few alternatives:

if [[ -f /sunstudio12/bin/sunf90 ]]; then
    export IMDI_COMPILER=/sunstudio12/bin/sunf90
if [ $? -ne 0 ]; then
    echo "Please specify location!"
    exit
fi

...or...

if ! { [[ -f /sunstudio12/bin/sunf90 ]] && export IMDI_COMPILER=/sunstudio12/bin/sunf90; }; then
    echo "Please specify location!"
    exit
fi

...or...

if ! [[ -f /sunstudio12/bin/sunf90 ]] || ! export IMDI_COMPILER=/sunstudio12/bin/sunf90; then
    echo "Please specify location!"
    exit
fi

Regards,
Alister

3 Likes

And which one is the best then ? (less parsing & less resource consumming) ?

1 Like

Every single command run on a UNIX/Linux/POSIX system will return an exit status. If that exit status is 0, the shell treats that as a boolean true. Any other exit status is treated as a boolean false.

Regards,
Alister

---------- Post updated at 02:21 PM ---------- Previous update was at 02:14 PM ----------

Actually, export always returns a 0 exit status, so it will never fail. Scrutinizer's code should work just as the original.

That said, I'll leave my post as is since that's a very unusual corner case. In just about every other situation, a command can return a non-zero exit status and the constructs would not be logically equivalent.

Regards,
Alister

1 Like

I certainly wouldn't challenge your assertion of that. But I would challenge any assertion that said return codes are always meaningful:

/root # yum install jiggery-pokery
Loaded plugins: fastestmirror, priorities
Determining fastest mirrors
 * addons: mirror.atrpms.net
 * base: mirror.switch.ch
 * extras: mirror.atrpms.net
 * updates: ftp.halifax.rwth-aachen.de
addons                                                   |  951 B     00:00     
addons/primary                                           |  202 B     00:00     
base                                                     | 2.1 kB     00:00     
base/primary_db                                          | 1.6 MB     00:01     
extras                                                   | 2.1 kB     00:00     
extras/primary_db                                        | 188 kB     00:00     
updates                                                  | 1.9 kB     00:00     
updates/primary_db                                       | 670 kB     00:00     
Setting up Install Process
No package jiggery-pokery available.
Nothing to do
/root # echo $?
0

Or perhaps alt's confusion is based on the interpretation of

if [[.....]] ; then
   [[ -f ... ]] && \
      export  ... || \
      { 
      echo ...; exit; 
      }

where the || relates not to the failure of the export command, but more to that of the test which precedes it?

1 Like

Your quite right Alister, however I suspect my interpretation is what the author of the script intended to write. Otherwise there is no logic to the error message and the exit statement. This illustrates how easily these logical ANDs and ORs get misinterpreted. That is precisely why I dislike them especially when there is a x && y || z concoction..

--edit--
Actually I think I was correct after all:
If the test fails then the statement after the && does not get executed since the left side is false. And then the part after the || gets excecuted since its left side was false and also the export will never fail, so that will not trigger the right side of the or.

OK, only now I read your added remark to your post. Probably all of us are right then :smiley:

1 Like

Hi, Scrutinizer:

Your interpretation is indeed correct, but its correctness hinges on export always returning 0. I mentioned that not to nitpick, but as a heads up for newbies.

Regards,
Alister

---------- Post updated at 02:48 PM ---------- Previous update was at 02:45 PM ----------

Heheheh. No argument here :wink:

1 Like

And even if it were just to nitpick, I quite enjoy your nitpicks :wink:

Me too. They're good nitpicks!

Keep up the good nitpicks :slight_smile:

Hmmm. POSIX says export returns 0 and doesn't mention any possible error conditions. However, some shells' export builtin can return a non-zero status. Perhaps it's better to be safe than sorry and not treat export's return as a given.

I appreciate the nitpick-appreciation :wink:

1 Like

But still then I am back to my original point and that it is unlikely what the author intended, especially given the error message, so we better correct the author. BTW, do you ever check return codes of export statements in your scripts?

1 Like

I agree. Your interpretation is faithful to the intent of the original version. The way the original code is written, it assumes export cannot fail.

Do I ever check export's return status? No comment :stuck_out_tongue:

1 Like