[Discussion] POSIX, the Love of Backticks and All That Jazz

But I love my back-ticks - I know exactly how to escape them (after too many years) - I always seem to end unbalanced with () .

However, I shall take the hint. (One more trick for this dog... aka - not too old yet!) :):wink:

You might want to try some formatting help in this case, when the subshell commands get more complex. This certainly helps me to keep track:

var=$( \
        command1 |\
        command2 |\
        command3 \
     )

I hope this helps.

bakunin

You don't need to use a \ newline.
Neither for $( ) that contains normal shell code that does not need to know it's within $( ) ,
nor for | that is one of the operators that work at the end of the line, expecting the operand on the next line.
You can even nest $( ) , unlike the old ` ` where each more level needs some extra \ escapes.

var=$(
  command1 |
  command2 |
  command3
  localvar=$(
    echo "hello world"
  )
)
1 Like

Hmm, 20 years of using ksh and i didn't know that. That is embarrassing.

bakunin

Then let me continue with lession#2.
Within $( ) there is a parser problem with the old style case statements.

#!/bin/bash
res=$(
  case $1 in
  1) echo 1;;
  esac
)
# syntax error in bash3 and ksh88
# workaround:
# (1) echo 1;;
echo "$res"

But bash4 and ksh93 have got a fix.

1 Like

Don't be. I have 38+ years on UNIX and I still use \ - because often - first I am assigning the "command" to a variable (as the string) and later am executing it (the variable). Same as I (must) do in files like configure.{ac|in}, Makefile, etc..

In short - better one \ too many that one short.

I'm not sure on using backquotes is wrong per se.
$(command) are both `command` are both currently valid syntax and in standards.
Exception being, that actually backquotes should work on even the oldest shells (and new ones), while other form might not.

If i'm not mistaken backquotes are still the lowest common denominator for command substitution if you wish your scripts to work anywhere without touching

But today it's hard to find such shells as defaults or even existing on operating systems.
So i tend to write scripts using $(command) method, as well as promote such way.

Regards
Peasant.

This is an interesting argument.

IMHO the "gold standard" of portability is POSIX: if something is POSIX, then it can (and should) be used, if it not, it should be handled with extreme care (and eventually not be used in absence of compelling reasons why it should).

The construct $(..) now is in fact the POSIX-standard for doing this (subshells) and backticks `...` are deprecated. This is why i use the former rather than the latter and recommend this practice to others.

For the same reason i write i.e. tail -n 5 instead of tail -5 . The former is POSIX, the latter deprecated. It may be that there is some (really old) system out there which would not recognise the new syntax but only the old one. This risk i am willing to take because, on the the other hand, there might be a really new system which has cut off old behaviorisms and only understands the current syntax.

I hope this helps.

bakunin

Bash is not standard on AIX. And many people I see using bash are using bash-4.2 not 4.4 - so when you say bash4 - do you mean any bash-4.X or are you talking about the X (again, most people just say bash - not bashX).

So, maybe - we should split this off - but please come up with a catchy "subject line" - as we are sort of "all over the place" - shells, POSIX, environments, ...

But backquotes are not depreciated if i'm reading the right standards !

2.6.3 Command Substitution

Command substitution allows the output of a command to be substituted in place of the command name itself. Command substitution shall occur when the command is enclosed as follows:

$(command)

or (backquoted version):

`command`

It's usage might be depreciated in modern shells as a good practice.
Bash or ksh manual on debian testing still shows backquotes as valid syntax.

It does not mention not to use it, or to prefer $(command) syntax.

Regards
Peasant.

Hi Peasant,
You are correct in saying that back-quotes are not deprecated as a method of performing command substitution in the standards. And, even though some people would like to, it is unlikely that the standards will formally deprecate back-quoted command substitution because so many existing (otherwise strictly conforming) shell scripts use them.

But, when writing new scripts (unless you intend to have them run on a pure Bourne shell that doesn't have $(command) command substitution), I would always suggest using the $(command) form... Note that:

  1. $(command) command substitutions can be nested,
  2. `command` command substitutions cannot be nested, and
  3. if you need to quote the results of a command substitution where the command contains a double-quoted string, the double quotes inside a $(command) command substitution are not affected by double quotes outside the command substitution; but double quotes inside a `command` command substitution produce undefined results if the command substitution is inside double quotes.
1 Like

I came across something like this in the early days of AudioScope and SOX.
I just assumed that it was me not coding correctly.
Thanks for the info.

Hi Don, `command` command substitutions can be nested, but the inner backquotes need to be escaped..

$ echo "$(echo "foo  $(echo "bar  baz")")" 
foo  bar  baz
$ echo "`echo \"foo  \`echo \\\"bar  baz\\\"\`\"`" 
foo  bar  baz

Also, IMO double quotes inside a `command` command substitution do not produce undefined results; they need to be properly escaped in accordance to the nesting level, which quickly leads to an escape hell, but it is not impossible. Why anyone would prefer backticks over $( ... ) is beyond me though..

1 Like

So done. Catchy enough for you? ;-))

bakunin

1 Like

Yes - although I am sure the move to the "expert users" helped as well.

As to why would anyone (still use) backticks:
a) I am not an expert scripter
b) I have used backticks over 38 years - as well as () (not $())
c) I make typo mistakes when using () - oops, that needs to be $()

In short - I write simple scripts - really simple ones - not save the world ones, and backticks work fine for me.

However, as I said before - I hope this dog is not too old - and I shall start to remember the $ in front of the ()

Lets not get deep into subshells.

I'm sure you experts don't have too many nested subshells in your code :wink:
In my opinion, it lowers the control you have in your program.

So if you have small, efficient script with no nested subshells, are backquotes still the lowest denominator e.g will it run without magic cookie on any unix OS ever produced ?

Example would be a simple mv script using basename command in subshell.

Any system you will encounter nowadays will most likely contain a POSIX compliant shell. So I would code for that and I really do not see a need for backticks anymore.

There hardly is a reason nowadays why a new script would need to be able to run in a Bourne shell, which would require the backticks..

I would never run the risk of having whatever shell executing my code. Out of pure paranoia you won't see any script without a shebang line stating the shell it is intended to run in explicitly.

You see, i once wrote shell scripts for an installed base of ~22k systems worldwide, ranging from IBM 42Ts and 43Ps (desktop systems) up to big SP/2s and everything in between. Believe me, whatever administrative horror you are able to think of - 5 systems somewhere had exactly this and then some. root not allowed to write a file in /tmp ? Filesystems with no more free inodes? A user named "root" but with a non-0 UID? I have seen all this and more.

Most of my scripts are not "small" therefore. Not, because they do so much, but because they take extreme care of error handling and take nothing i can think of for granted.

basename is IMHO a bad example. I would do that with parameter expansion as (in the interest of speed) anything else that could be done with it.

bakunin