The ultimately sad part was the professor in a Sun OS machine.
In a corner with no where to go, giving demerits because his bash was older than he realized.
Reminds me of my college professor that claimed you don’t have to close HTML tags (some you absolutely do) and I proved that you do. Not all of them, but most of them. (Netscape Navigator Days)
> When I was a young, green, university student, I was forced to use test(1) as the only true way to do testing in shell scripting. […] Yeah, I was also forced to not use semicolons as they were evil (according to my professor, any comment unneeded!).
The author’s professor clearly went overboard, but doesn’t this entire anecdote demonstrate the value of teaching it this way? Having green students call the `test` binary provides more insight into how UNIX operates, and gets them using a UNIX mindset. They can discover the syntactic shortcuts later.
Reminds me of my rather memorable introduction to special characters invoking functions, seeing this dastardly little quip in the email signature of someone in a mailing list (circa '95 or so).
:(){:|:&};:
My curiosity piqued, I pasted it into the shell on my terminal in a pure example of FAFO. The poor little Sparc 5 I was using ground to a halt over the course of about ten seconds. The reboot was as hard as the lesson. xD
In college I took a database class, it was pretty basic overall as I had been playing with MySQL for a few years at that point. On the final exam I got a 90/100. The test was 10 questions that just had you write SQL to answer the question. I got all the queries 100% correct... except... I didn't put a ";" after each query. On a written test. I'm still a little bitter about that.
/bin/[ as a binary looking for it's own "]" closing bracket!
What a nasty syntax hack!
I wonder what the motivation was for doing this rather than just implementing test expression support directly in the shell?
I just tried and bash also accepts some other odd filenames in place of "[", so you can do:
ln -s /bin/test "-"
ln -s /bin/test "$"
And use either of these in place of "[" (assuming they are on your path). Of course they still expect the closing "]" since that requirement comes from /bin/test.
It's an interesting way to extend bash in a confusing way! You could write a "$" utility that did something else entirely, perhaps looking for a "closing $" too, then write something like:
Here is the part of the test.c source from V7 Unix:
main(argc, argv)
char *argv[];
{
ac = argc; av = argv; ap = 1;
if(EQ(argv[0],"[")) {
if(!EQ(argv[--ac],"]"))
synbad("] missing","");
}
argv[ac] = 0;
if (ac<=1) exit(1);
exit(exp()?0:1);
}
So, if the professor was missing the "[" command, they were missing a link. More likely, they had a weird orthodoxy about using "test" instead of "[" because reasons. One good reason to use "test" instead of "[" in a Bourne shell control statement is if you are running a list of commands between "if" and "then", and the test is the last part of the list.
Another good place to use "test" is if you are not in a control statement and you are just setting $?.
The [[…]] built-in test version was introduced in Peter Korn's korn shell, ksh88 IIRC. As where various other modernized notations like array variables, process substitution or
$(command)
as a much more readable version of the backquotes version.
I knew that `[` was notionally the same as `test`, but had never 'checked'. I just assumed `[` was a built-in that conformed rather than them actually being the same.
So I very much enjoyed following along with the article, first seeing that `ls -il /bin/test` and `ls -il /bin/[` are at different inodes, then md5summing and seeing they are different, getting concerned, then the article revealing that is the case now (I'm trusting rather than verifying about the separate builds).
I was then very satisfied to recall that `[[` is a built-in (as `[[` isn't portable between all shells).
I don't like bash, and this kind of esoteric, hard-to-remember syntax is a big reason why. Software developers and computer users should want their shell to be easy to use and reason about, just as they reasonably want this from their general-purpose software development languages.
bash is a UNIX legacy tool from the 80s that lingers on in software written today because it's part of the POSIX standard (well, sh, which is close enough), and because generations of developers on UNIX-like systems can be assumed to be familiar with it. I don't think this is a good thing, and I would like to see active efforts to replace the use of bash with better, more-modern scripting languages that provide an easier-to-understand more-reliable experience for users.
19 comments
[ 2.5 ms ] story [ 39.9 ms ] threadI'm still not sure when to use one or the other. I use double brackets by default until something doesn't work.
In a corner with no where to go, giving demerits because his bash was older than he realized.
Reminds me of my college professor that claimed you don’t have to close HTML tags (some you absolutely do) and I proved that you do. Not all of them, but most of them. (Netscape Navigator Days)
The author’s professor clearly went overboard, but doesn’t this entire anecdote demonstrate the value of teaching it this way? Having green students call the `test` binary provides more insight into how UNIX operates, and gets them using a UNIX mindset. They can discover the syntactic shortcuts later.
https://mywiki.wooledge.org/BashFAQ/031
/bin/[ as a binary looking for it's own "]" closing bracket!
What a nasty syntax hack!
I wonder what the motivation was for doing this rather than just implementing test expression support directly in the shell?
I just tried and bash also accepts some other odd filenames in place of "[", so you can do:
ln -s /bin/test "-"
ln -s /bin/test "$"
And use either of these in place of "[" (assuming they are on your path). Of course they still expect the closing "]" since that requirement comes from /bin/test.
It's an interesting way to extend bash in a confusing way! You could write a "$" utility that did something else entirely, perhaps looking for a "closing $" too, then write something like:
if $ args $;
then
fi
Another good place to use "test" is if you are not in a control statement and you are just setting $?.
Edit: EQ() is defined as:
https://docs.oracle.com/cd/E36784_01/html/E36870/ksh88-1.htm...
While learning the Bourne shell as acstudent, I was rapidly lured by csh and then tcsh, but Tom Christiansen's pamphlet https://everything2.com/title/csh+programming+considered+har...
and (or?) the appearance of Paul Falstad's Z-Shell saved me ;-0
So I very much enjoyed following along with the article, first seeing that `ls -il /bin/test` and `ls -il /bin/[` are at different inodes, then md5summing and seeing they are different, getting concerned, then the article revealing that is the case now (I'm trusting rather than verifying about the separate builds).
I was then very satisfied to recall that `[[` is a built-in (as `[[` isn't portable between all shells).
bash is a UNIX legacy tool from the 80s that lingers on in software written today because it's part of the POSIX standard (well, sh, which is close enough), and because generations of developers on UNIX-like systems can be assumed to be familiar with it. I don't think this is a good thing, and I would like to see active efforts to replace the use of bash with better, more-modern scripting languages that provide an easier-to-understand more-reliable experience for users.