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)
Precisely because those older systems didn’t link to it!
So my comment still stands.
Not to speed up bash scripts? Launching a process for simple if statements such as those checking whether a file exists is fairly expensive.
Ya’ll are tracing the same logic of the 90s here.
Terrible…
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.
I do think it makes sense to have beginners use `sh` instead of `bash`.
Getting a Linux or Unix system to boot without a proper shell would be another complication, so a system completely without a she'll? I expect that to either be easy nor useful.
$ which [
/bin/[
$ type [
[ is a shell builtin
The same is true for the `test` command: $ which test
/bin/test
$ type test
test is a shell builtin if "[" "$foo" "==" "bar" "]"; then ... :(){:|:&};:
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. xDI'm confused. What happened on reboot?
As an extra sting, a hard reboot can be damaging if the software and hardware is not correctly handling power interruption, which was much more likely in the 90's.
u(){u|u&};u
AKA, fork u. :(){:&;:};:
This is the same number of characters but doesn’t use a pipe, and I was never able to figure out why it seems so universally to use a pipe.It was a weird course, though. Because we spent so long learning Prolog, the second half of the course was really rushed - lots of learning about English grammar and syntax trees, and how you could model them in different ways, and then the last lecture was just "oh, by the way, here are all the ways this doesn't work and is a complete dead end - your exam is on the 14th".
IIRC there was a part two to the course, but I think it clashed with something I was more interested in so I never took it. It was cool to learn Prolog, but I wish it had been a whole course on just Prolog and actual present-day use-cases, as opposed to this weird half-and-half course about an approach to NLP that even back then wasn't being pursued with much enthusiasm.
Its not really theoretical or applied CS, but it is a core skill for meaningfully doing applied CS.
/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
And it's fully legit (from the draft C standard, 5.1.2.2.1, § 2 "Program startup"):
> The parameters argc and argv and the strings pointed to by the argv array shall be modifiable by the program, and retain their last-stored values between program startup and program termination.
https://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf [pdf]
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 $?.
Edit: EQ() is defined as:
#define EQ(a,b) ((tmp=a)==0?0:(strcmp(tmp,b)==0))
char *tmp; $(command)
as a much more readable version of the backquotes version.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.
theandrewbailey•3w ago
I'm still not sure when to use one or the other. I use double brackets by default until something doesn't work.
stabbles•3w ago
When unsure, use shellcheck.
a3w•3w ago
duskdozer•3w ago
stabbles•3w ago
duskdozer•3w ago
And this isn't meant snarkily - why should I care if my scripts are portable? I've worked on a number of different devices and types but have seemingly always had access to bash.
PhilipRoman•3w ago
ndsipa_pomu•3w ago
I personally use ((...)) for arithmetic tests and [[...]] for all other tests as I just target new versions of BASH and don't care much about POSIX compatibility.
PhilipRoman•3w ago
This can evaluate arbitrary code: [[ "${payload}" -eq 42 ]]
Here is one example of a malicious payload:
ndsipa_pomu•3w ago
Now I need to figure out whether (( payload == 42 )) is safe.
ndsipa_pomu•3w ago
account42•3w ago
nickjj•3w ago
I usually default to [ ... ] unless I need features that double brackets provide.
ndsipa_pomu•3w ago
jonhohle•3w ago
jcynix•3w ago
zzzeek•3w ago
SAI_Peregrinus•3w ago
zzzeek•3w ago
xp84•3w ago
Honestly though I’ve been much happier since I stopped writing anything complex enough to have conditionals in Shell. Using a real scripting language like Ruby, Python, even PHP or Perl if you know them, is better.
In the Ruby case I just use `%x( … )` when I need to run shell commands (there are some things shell does great like passing pipelines of text through 5 programs) and let the logic part be in Ruby.