# sh shell scripts have an ugly syntax ?



## Alain De Vos (Aug 20, 2020)

"If" stuff are very ugly, [[ ...]] and [...]. But are there better alternatives ?

Alternatives, e.g. the following program gets more ugly in python. Because of the IO,
#!/bin/sh
cat mytext.txt | sort | uniq > result.txt

What are your opinions about bash or lua ? Some hate bashism.
sh is old can also be a reason to drop it.


----------



## ralphbsz (Aug 20, 2020)

On one hand, syntax is the least of the problems when writing software. When you write a large software project, 90% of the work goes into planning, design, project management (who does what, how to you stage things, how do you handle bugs, release mechanism, source control). And of that design is particularly important. In comparison, these differences are really minor:

```
if elefant == flying:
    do_fly(elefant)

if (elefant == flying) {
    do_fly(elefant)
}

if [ elefant -eq flying ] ; then
  do_walk elefant
fi

IF ELEFANT = FLYING THEN
    PERFORM DO_FLY VARYING ANIMAL AS ELEFANT
END-IF
```

On the other hand, for beginners or really short pieces of code, syntax makes a difference.


----------



## Mjölnir (Aug 20, 2020)

Modern languages have built-in capabilities for unit tests (1x1 of good programming: write tests 1st, then code until tests pass), constraints, produce documentation from comments etc.pp.  To avoid common syntax errors by providing a "better" syntax was one of the design goals of Python.  It also allows for the adoption of various programming paradigms, so you can choose the one that fits the problem best to implement _elegant_ solutions (in general, these are easier to maintain).  LUA is definitely the way to go for embedded scripting, i.e./e.g. for pkg & zfs.  I would not recommend bash(1) scripts just because it provides some handier facilities.  Choose standard POSIX shell instead.


----------



## Alain De Vos (Aug 20, 2020)

Ralphbsz, form has also some importance because it frees the mind of doing unnecessary mental juggling.
Remember Einstein inventing a notation which fitted his problem.
What I don't like about python is let's say, trapping signal, difficulty in piping output from one program to another, having to call popen3.
pkg info | awk '{print $1}' | xargs -I {} pkg remove {}
Python is not well fitted to do this I think
And sh scripts are prone to syntax errors I find, just edit /etc/rc.subr ,which you should not do , I know


----------



## Jose (Aug 20, 2020)

One of the more startling features of shell is dynamic scoping:





						Bash Tutorial => Dynamic scoping in action
					

Learn Bash - Dynamic scoping in action




					riptutorial.com
				




Fortunately I've only ever seen it used once.


----------



## kpedersen (Aug 20, 2020)

Jose said:


> Fortunately I've only ever seen it used once.



Was it "used" to explicitly confuse the poor sucker maintaining it?


----------



## Jose (Aug 20, 2020)

anonymous9 said:


> Racket
> 
> ```
> #lang racket
> ...


What the heck does `string<?` mean?


----------



## Alain De Vos (Aug 20, 2020)

As alternative to racket there is kawa,


			https://www.gnu.org/software/kawa/
		

With objects, and swing.
Both are fast, chicken is slow.

Also ocaml has interesting features.

But doing ,
pkg info | awk '{print $1}' | xargs -I {} pkg remove {}
and for instance doing it interactively and non-interactively and catching errors.
Many languages fail.

PS: As for dynamic scoping, it can be interesting if you invent a new language, because we are short of.


----------



## shkhln (Aug 20, 2020)

Jose said:


> What the heck does `string<?` mean?



Just a function name.


----------



## Jose (Aug 20, 2020)

shkhln said:


> Just a function name.


You mean this?


			4.4 Strings
		


Where are `str1` and `str2`?


----------



## shkhln (Aug 20, 2020)

It's the function itself (_string<?_) that is being passed to _sort_. Here a rough (syntax only) javascript translation:

```
function rackSort(f) {
  return sort(removeDuplicates(File.lines(f)), function(a, b) { return a < b; });
}
```


----------



## Alain De Vos (Aug 20, 2020)

On Lua. Could you write the following two in Lua and would that be an improvement ? Why or why not ?
Both are related but use a different language.









						freebsd-src/init.c at master · freebsd/freebsd-src
					

FreeBSD src tree (read-only mirror). Contribute to freebsd/freebsd-src development by creating an account on GitHub.




					github.com
				









						[base] Contents of /releng/12.1/libexec/rc/rc.subr
					






					svnweb.freebsd.org


----------



## 20-100-2fe (Aug 20, 2020)

Alain De Vos said:


> Ralphbsz, form has also some importance because it frees the mind of doing unnecessary mental juggling.



For programming, yes. Not for scripting. And your post is about "shell scripting".
Maybe you'd like to read this thread about the exact same question.


----------



## memreflect (Aug 21, 2020)

I personally think shells/fish is very useful to most people; I'd say it's a great replacement for those who like more featureful shells such as bash, ksh, and zsh.  For people who don't mind putting up with some annoyances and "fixing up" their shell with the shell's equivalent of $HOME/.profile the same way you'd fix up bash and ksh, there are two shells with strong similarities to each other: shells/rc and shells/es.  All three alternative shells are decent when it comes to scripting, but they also all have their own quirks and challenges to overcome.  shells/rc is my personal preference.  

And there are plenty of other shells with syntax that differs from sh, such as shells/elvish and shells/xonsh, though I admittedly haven't tried any of them.

I think shell innovation is difficult in general.  Languages like Python and Perl are powerful, yet verbose, while sh sacrifices such powerful features in favor of a less verbose syntax full of symbols rather than words in English or some other language, which contributes to its poor readability.  In addition, it still needs to be usable in an interactive session.  A balance between those requirements (and possibly several others) must be struck, so sacrifices must be made somewhere.

On top of all of that, a new shell deviating from existing conventions can be problematic when attracting new users or porting scripts.  In the case of fish, you couldn't use something like `command1 && command2` until v3.0 (`command1; and command2` was fishy).

Ultimately, sh is the most portable syntax, but there are definitely better shells, whether you're talking about interactive use or scripting.


----------



## mark_j (Aug 21, 2020)

memreflect said:


> I personally think shells/fish is very useful to most people; I'd say it's a great replacement for those who like more featureful shells such as bash, ksh, and zsh.  For people who don't mind putting up with some annoyances and "fixing up" their shell with the shell's equivalent of $HOME/.profile the same way you'd fix up bash and ksh, there are two shells with strong similarities to each other: shells/rc and shells/es.  All three alternative shells are decent when it comes to scripting, but they also all have their own quirks and challenges to overcome.  shells/rc is my personal preference despite it not even supporting tilde expansion.
> 
> And there are plenty of other shells with syntax that differs from sh, such as shells/elvish and shells/xonsh, though I admittedly haven't tried any of them.
> 
> ...


Jeez, give some love to zsh! Pah-leez!


----------



## forquare (Aug 21, 2020)

I personally don't find shell syntax particularly ugly.  I dropped Bash for scripting years ago, so there's no `[[...]]` vs `[...]` for me.

But maybe it's what  you're used to?  I've been writing shell scripts for over a decade and it's often the tool I go to first.  Looking at Objective-C I'm blinded by the syntax initially and could say I find it ugly.
Admittedly not the syntax, but looking at the style of much C code I find it ugly and non-intuitive (mainly due to the fact that (a) I've done little C, and (b) variable names seem to use excessive use of acronyms and shorthand to make them near indecipherable for anyone not intimate with the program).


----------



## Deleted member 63539 (Aug 21, 2020)

forquare said:


> I personally don't find shell syntax particularly ugly.  I dropped Bash for scripting years ago, so there's no `[[...]]` vs `[...]` for me.
> 
> But maybe it's what  you're used to?  I've been writing shell scripts for over a decade and it's often the tool I go to first.  Looking at Objective-C I'm blinded by the syntax initially and could say I find it ugly.
> Admittedly not the syntax, but looking at the style of much C code I find it ugly and non-intuitive (mainly due to the fact that (a) I've done little C, and (b) variable names seem to use excessive use of acronyms and shorthand to make them near indecipherable for anyone not intimate with the program).


Yeah. Objective C function names sometimes very long indeed. Objective C needs a good IDE.


----------



## 20-100-2fe (Aug 21, 2020)

forquare said:


> I personally don't find shell syntax particularly ugly.  I dropped Bash for scripting years ago, so there's no `[[...]]` vs `[...]` for me.



Shell syntax is well suited for scripting.
If you need a "more powerful" or "more legible" language, it very probably means that you're doing application development and no longer scripting.
Scripting is intended for task automation, the "real work" being done by the applications the script launches.
This means *a scripting language needs to make application execution as simple as possible* because it's what it does most of the time.
In a programming language, executing another application doesn't need to be simple because your application seldom does it.
(Remember: the Unix philosophy.)
Unlike a script, an application basically parses data (or waits for user input), uses it to produce other data and outputs or persists it.
*A programming language thus needs to make data representation as simple as possible.*
Scripting and application development are complementary activities, so are their languages.


----------



## olli@ (Aug 21, 2020)

Alain De Vos said:


> #!/bin/sh
> cat mytext.txt | sort | uniq > result.txt


To be honest, I don’t see what the problem is with the above little script. Looks fine to me, and I wouldn’t try to rewrite that in any other language.

Well, one thing that I would change is the abuse of cat(1):
`sort mytext.txt | uniq > result.txt`

Also, sort(1) already has the `-u` option, so uniq(1) is superfluous, too:
`sort -u mytext.txt > result.txt`


----------



## Alain De Vos (Aug 21, 2020)

The following is quite readable,

```
#!/usr/local/bin/zsh
function doit {
    a=(do re mi fa sol)
    a[3]=()
    for b in $a[2,4]
        do
            echo $b
        done
}

doit
```

It has no ";" , which i find weird.


----------



## olli@ (Aug 21, 2020)

Alain De Vos said:


> It has no ";" , which i find weird.


Well, in the bourne shell and its derivatives (including zsh), “;” separates commands just like a newline. So, if you always use newlines for separation, you never need to have “;”.

So, the following three variations are exactly identical:

```
for i in foo bar baz; do echo $i; done
```


```
for i in foo bar baz; do
        echo $i
done
```


```
for i in foo bar baz
do
        echo $i
done
```
Usually, script authors chose the second variation, probably because it comes closest to the structure of other languages.

By the way, if you want to write zsh scripts as portable as possible, the first line should look like this:

```
#!/usr/bin/env zsh
```
That’s because the location of the zsh binary can differ. Most Linux systems have it in /usr/bin, sometimes it is somewhere under /opt, and the BSDs usually have it in /usr/local/bin. When using the env(1) trick, it doesn’t matter where the zsh binary is located, it just has to be somewhere in the users `$PATH`.


----------



## ekvz (Aug 21, 2020)

I wouldn't call it ugly. A bit archaic maybe. I got used to it over the years i guess and it's all in the eye of the beholder. If i'd list the languages i consider to be ugly there would probably be a lot of people disagreeing and understandably so.


----------



## 8bitGlitch (Aug 21, 2020)

Alain De Vos said:


> "If" stuff are very ugly, [[ ...]] and [...]. But are there better alternatives ?
> 
> Alternatives, e.g. the following program gets more ugly in python. Because of the IO,
> #!/bin/sh
> ...


Do you have to use 'shell'? I am just now learning Lua; however, it does not have 'batteries' included unlike Python, yet I think this is a good thing. If you are not limited to only using 'shell' then maybe Perl would be an option. I know a lot of folks think it is ugly, and could have legacy management issues, but for something quick and dirty I find it is a better solution then Python.

Lua is getting used a number of networking devices and it seems if the industry is leaving Tcl behind, so Lua is a great option for the coming future if that is your targeted sector of the industry.


----------



## rootbert (Aug 21, 2020)

the unix tools combined with a pipe are great, however, I fully agree that shell scripting is awkward (apart from the nice one-liners) ... maybe you like python plumbum ... https://plumbum.readthedocs.io/en/latest/local_commands.html#guide-local-commands - still not perfect but I like it.


----------



## Alain De Vos (Aug 22, 2020)

This looks also interesting,








						GitHub - worace/coque: Plumbum for ruby, with native code streaming support
					

Plumbum for ruby, with native code streaming support - GitHub - worace/coque: Plumbum for ruby, with native code streaming support




					github.com


----------



## Hakaba (Aug 22, 2020)

«if» in programming langage did not match the «if» in natural langage.


ralphbsz said:


> if [ elefant -eq flying ] ; then do_walk elefant fi




```
[elefant -eq flying ] && do_walk elefant
```

I see in a lot of code this kind of things : (I was a senior code reviewer in past job)


```
if ( condition ) then return true else return false
```

Obviously, the real code is more complicated, but you maybe see the same things.

When I was student, a professor say «object programing was invented to replace `if` statement»

And it is not as falsy as this sound...


----------



## ralphbsz (Aug 22, 2020)

olli@ said:


> By the way, if you want to write zsh scripts as portable as possible, the first line should look like this:
> 
> ```
> #!/usr/bin/env zsh
> ...


That env trick has advantages and disadvantages. Advantage: the script is more likely to work, because the user probably has their path set correctly.

Disadvantage: Whether the script works or not now suddenly depends on a user setting; a harmless-looking change to the PATH variable, and suddenly things start breaking. Another disadvantage: there may be different versions of the same program installed in different places, and using the env trick relies implicitly on people ordering things sensibly in the path.

I'm not saying to never use /usr/bin/env, just warning people that a little discipline is still required.


----------



## ralphbsz (Aug 22, 2020)

Hakaba said:


> ```
> [elefant -eq flying ] && do_walk elefant
> ```


I don't like that. Same with the perl idiomatic thing: "do_something || die". It relies on the short-circuit property of evaluation, which I find unintuitive when reading the code (although the perl idiom has become very common, so one recognizes it).



> ```
> if ( condition ) then return true else return false
> ```


Yeah, that's bad. Just as bad is the following:

```
if (boolean_variable == True) ...
```
and even worse is:

```
if (boolean_variable == False) ...
```

There are many ways to write bad code.


----------



## 20-100-2fe (Aug 22, 2020)

In any programming language, it is always a good idea to craft one's code so it gets as close as possible to English sentences.
Benefits are invaluable and, as long as there's no tax on source file size, there's no penalty.


----------



## Alain De Vos (Aug 22, 2020)

Some unreadability is sometimes due to overdue of syntactic sugar.
Ralph & Hakaba, what is good practice for the examples you've given.


----------



## Alain De Vos (Aug 22, 2020)

In bash i had one , notice the difference between [ and [[ , I was surprised.
Code without an error:

```
if [ "$s2" == "$s2" ]
    then echo "equal"
fi

if [[ "aaa" < "bbb" ]]
    then echo "in order"
fi
```

Whereas this gives gave error:

```
if [ "aaa" < "bbb" ]
    then echo "in order"
fi
```
>>> bbb: No such file or directory


----------



## Alain De Vos (Aug 22, 2020)

A bash one :

```
age=9
echo $age
case $age in
[0-15])
    echo "Too young"
    ;;
*)   
    echo "Too old"
    ;;
esac
```

Prints Too old


----------



## 20-100-2fe (Aug 22, 2020)

This is an improper use of 'case'.
To test whether a value belongs to an interval in any language (not just shell scripts), you should use 'if'.



Alain De Vos said:


> A bash one :
> 
> ```
> age=9
> ...


----------



## 20-100-2fe (Aug 22, 2020)

< and >can only be used as relational operators between [[ and ]].
Otherwise, they are interpreted as redirections.

Man pages are clear: see section CONDITIONAL EXPRESSIONS in "man bash" for [[ ]] and "man test" for [ ].



Alain De Vos said:


> Whereas this gives gave error:
> 
> ```
> if [ "aaa" < "bbb" ]
> ...


----------



## Márcio Rezende (Aug 23, 2020)

When in Rome, do as the Romans do (St. Augustine)

I've started a simple hobby project some years ago (rolling up until now), using C, basically to keep my mental cogs spinning. After playing with it I realise that I was not programming but scripting. Using system facilities - ls, sort, write, etc - calling it with system(). "Plumbing" in essence.

So I started with bash... Ok... But I had same sensation of "ugliness" described at thread start. And "plumbing" too much avoiding idioms of bash and connecting sed, awk, the "terrible  2>&1"...

So I restarted everything using the "fancier, whistler and bell'ser" python... Well, after some lines of code, I decided to run it in other system... Ooops... I've to install python... Configure python... Equalize python... Diaper changing python... Powdering python... I was not programming or scripting anymore, but tweaking  things!

After some frustration... I restart again with bash. I needed some associative arrays to keep things tidy... Well it works fine in bash (despite of awful and confusing syntax). I detect it was my problem not bash problem. And finally I started with awk and realise again that I was doing programming  again, not scripting anymore.

So I started using FreeBSD and everything changes once again... Bash on FreeBSD seems not to be welcome. I suspect that I should have used shell and Posix (like a recommedation above).

At end my perception is if you are doing too much tweaking or jugglery with your code,  your real need is to revise that code and split (and test) in little parts. Script where to script, program where to program and connect those pieces with json.

If you are a programmer you are supose to deal with logic. Languages are tools to deal with  logic. Languages are not the road or destiny, but the car. It pays learn to drive!

Some tools are designed to accomplish "culture" system's needs. You have to be flexible enough because modern systems are very flexible these days. If you try impose your needs chances are you'll be in hot water.

Roughlly all my problems come from the stubborn of want to see things work quick and the frustration to deal with dirtness of shortcuts  ... Avoiding the wise of learning by R(&U*)TFM.

*(and understand)


----------



## ekvz (Aug 23, 2020)

Márcio Rezende said:


> So I restarted everything using the "fancier, whistler and bell'ser" python... Well, after some lines of code, I decided to run it in other system... Ooops... I've to install python... Configure python... Equalize python... Diaper changing python... Powdering python... I was not programming or scripting anymore, but tweaking  things!



Agreed. While i hold nothing against python in general i don't think it's an ideal choice for system scripting. It's way to heavyweight which on a regular system might not be really noticeable but as soon as it comes to minimal setups every dependency on python (or perl for that matter) that exists just to run some rather simple script becomes an annoyance and as you said python doesn't always equal python either.



Márcio Rezende said:


> Bash on FreeBSD seems not to be welcome. I suspect that I should have used shell and Posix (like a recommedation above).



I personally don't think bash in itself is bad or anything. The problem is more with how bash has managed to become synonymous with shell scripting and a lot of people not even realizing that there might be more portable (and also less resource intensive) ways to solve the problem they are facing. This is a obviously particularly widespread in the linux community where bash is practically everywhere and it's easy to forget that this actually isn't the norm (there was even a time when Debian had linked /bin/sh to /bin/bash because not doing so would risk breaking it's boot scripts...).

Still when a certain feature noticeably improves a script and there is no reasonable way to emulate it and/or reorganize the code to avoid the need i don't see anything wrong with targeting bash (or *ksh, or whatever shell supports your desired feature). On the contrary i will be quite happy you didn't chose python or perl. In my eyes putting a lone additional executable on my system is nothing compared to a full blown scripting language environment even if it's only use is to run a single script.


----------



## Alain De Vos (Aug 23, 2020)

Could I say use [[ ]] always and never  [] even if it means a little more typing on the keyboard ?


----------



## kpedersen (Aug 23, 2020)

Márcio Rezende said:


> Powdering python... I was not programming or scripting anymore, but tweaking  things!



This is so true. Whenever I see a potentially useful python program, the README is always filled with this wild goose chase of dependency management and outright faffing. Most of it is outside of the OS package manager too (and using PIP) which makes maintenance a chore.

It is a shame because the language itself isn't too bad. It is fairly sane and boring (which is a good thing!).
I can also see why it is like this, for example it cannot natively connect to C libraries (basically the underlying OS) so you need bindings (via PIP) which are usually only maintained by a single person in their free time and often suffer from bitrot.

<ramble>
I think the only way to solve this is to include a tiny C compatible compiler within Python itself. Not because C is your end goal but only so that it can consume C headers / libraries and connect to the underlying OS. I strongly suspect this is what has contributed to C++'s success. If C++ couldn't access C libraries, it would be fairly dead in the water.


----------



## 20-100-2fe (Aug 23, 2020)

Alain De Vos said:


> Could I say use [[ ]] always and never  [] even if it means a little more typing on the keyboard ?



If your scripts are bash-only, why not?

I had the same idea not so long ago.
Then, I tried FreeBSD and realized bash was not in base, so I tried and rewrite my scripts with sh to reduce their dependencies.
I turned out this exercise improved the readability of my scripts because most bash internals/extensions I was using where provided by expr, sed and tr.
The lines in my scripts are now longer, but easier to read (and thus maintain) than bash-specific stuff.
It also forced me to be clearer about the distinction between scripting and programming, which improves my productivity.

In the end, I consider NOT using bash a blessing in disguise.


----------



## Alain De Vos (Aug 23, 2020)

To be in base in not really that important.
mksh has only one dependancy /lib/libc.so.7


----------



## ekvz (Aug 23, 2020)

Alain De Vos said:


> Could I say use [[ ]] always and never  [] even if it means a little more typing on the keyboard ?



While i don't know the answer to your exact question the reverse is certainly true. I'd say i've written my fair share of shell scripts over the years and i can't remember a single time when i felt limited by `[ ... ]` / `test` but then i've hardly ever used bash so maybe i just don't know what i have been missing out on.



Alain De Vos said:


> To be in base in not really that important.
> mksh has only one dependancy /lib/libc.so.7



There is also a variant named lksh made for scripting which supposedly is even more lightweight but i don't know if there is an easy way to install it on FreeBSD. It seems the mksh port has no option to build it and it does not have it's own port either. Not that this is much of a problem with mksh itself being quite efficient already and also having dual use as a (in my opinion) pleasant interactive shell.


----------



## Alain De Vos (Aug 23, 2020)

This link was interesting.





						Unix Shells: Bash, Fish, Ksh, Tcsh, Zsh - Hyperpolyglot
					






					hyperpolyglot.org
				



I think I'll stick to mksh and use zsh when a feature is needed.


----------



## ralphbsz (Aug 23, 2020)

Alain De Vos said:


> Could I say use [[ ]] always and never  [] even if it means a little more typing on the keyboard ?


Why? What advantage does [[ give over [?

In the old days, it ran faster. Today, with good caching in the file system, and very optimized fork/exec, I doubt that it makes a measurable difference. Today, the restricted resource is usually not CPU time, but human time, in particular human time spent debugging, porting, organizing. So I prefer to write my shell scripts relatively simple, using a sort of "lowest common denominator" between shells. While I do use bash (even on FreeBSD, even as my login shell, even for root in spite of the recommendation to not do that), I try to write my scripts using sh.


----------



## kpedersen (Aug 23, 2020)

Isn't '[' always built in for sh anyway?






						builtin
					






					www.freebsd.org
				




The builtin manpage suggests it is. So [[ shouldn't offer any speed advantage.


----------



## ralphbsz (Aug 24, 2020)

kpedersen said:


> Isn't '[' always built in for sh anyway?
> The builtin manpage suggests it is. So [[ shouldn't offer any speed advantage.


It is a builtin for sh (in the sense of FreeBSD's default /bin/sh) and for bash. I knew about bash, but I actually had to check for sh.


----------



## a6h (Aug 24, 2020)

kpedersen said:


> Isn't '[' always built in for sh anyway?


It was added (probably!) in System III shell (1981):

> Seventh Edition (aka Version 7) Unix shell, (1979)
Quote from https://www.in-ulm.de/~mascheck/bourne/#version7


> no "[" built-in available (even not as external command on Version 7), but only the external "test"


manpage: https://www.in-ulm.de/~mascheck/bourne/v7/

> System III shell (1981)
Quote from https://www.in-ulm.de/~mascheck/bourne/#system3


> built-in "test", aka "[", added (the latter actually was always existent in code, but commented out)


manpage: https://www.in-ulm.de/~mascheck/bourne/sys3/


----------



## olli@ (Aug 24, 2020)

ralphbsz said:


> I don't like that. Same with the perl idiomatic thing: "do_something || die". It relies on the short-circuit property of evaluation, which I find unintuitive when reading the code (although the perl idiom has become very common, so one recognizes it).


I don’t like that either. But I think “`die … unless …`” is _much_ worse. Introducing the keyword “unless” is one of the many mistakes in Perl.


----------



## olli@ (Aug 24, 2020)

ralphbsz said:


> Why? What advantage does [[ give over [?


Cleaner syntax, less ambiguity, lower risk of “surprises”. I always use `[[...]]` when I use zsh or bash. Of course, if I need to stay compatible with FreeBSD’s /bin/sh, I’m restricted to use `[...]` only.

By the way, `[[...]]` is a shell keyword, while `[...]` is a built-in command. Normally that doesn’t make a difference, it only matters when you’re trying to do strange things, for example running it in the background (which works for `[...]` because it’s executed like a normal command, but it doesn’t work for `[[...]]`).

The last shell I know that did _not_ have `[...]` built-in was Solaris’ /bin/sh. So, each time a script did `if [...]; then` it had to fork(2) + execve(2) an external command with all of its overhead. Consequently, scripts that did that very often ran very slow. In such cases, replacing `#!/bin/sh` in the script’s first line with `#!/usr/xpg4/bin/sh` gave a considerable speed-up.


----------



## Jose (Aug 25, 2020)

Didn't some systems have a binary executable file called `[`? Am I misremembering


----------



## Alain De Vos (Aug 25, 2020)

there is a "[" in /bin


----------

