== One thing that makes the Bourne shell an odd language In many ways, the Bourne shell is a relatively conventional programming language. It has a few syntactic abnormalities, a few flourishes created by the fact that it is an engine for running programs (although other languages have featured equivalents of _$(...)_ in the form of various levels of 'eval' functionality), and [[a different treatment of unquoted words ShellsVsScriptingLanguages]], but the overall control structure is an extremely familiar Algol-style one (which is not surprising, since [[Steve Bourne really liked Algol ../programming/BourneGol]]). But the Bourne shell does have one thing that clearly makes it an odd language, namely that it has outsourced what are normally core language functions to external programs. Or rather it started out in its original version by outsourcing those functions; versions of the Bourne shell since then have pulled them back in in various ways. Here I am thinking of both evaluating conditionals via _test_ aka _[_ and arithmetic via _expr_ (which also does some other things too). (Bourne shells have had _test_ as a builtin for some time ([[sometimes with some annoyances UnixWithoutTest]]) and built in arithmetic is often present these days as _``$((..))''_.) There's no reason why _test_ has to be a separate program and neither _test_ nor _expr_ seems to have existed in Research Unix V6, so they both appeared in V7 along with the Bourne shell itself. They aren't written in [[BourneGol ../programming/BourneGol]], so they may not have been written by Steve Bourne himself, but at least _test_ was clearly written as a companion program ([[the V7 Bourne shell manpage http://minnie.tuhs.org/cgi-bin/utree.pl?file=V7/usr/man/man1/sh.1]] explicitly mentions it, among other things). I don't know why the original Bourne shell made this decision. It's possible that it was simply forced by the limitations of the PDP-11 environment of V7. Maybe a version of the Bourne shell with _test_ and/or _expr_ built into the main shell code would have either been too big or just considered over-bloated for something that would mostly be used interactively (and thus not be using _test_ et al very often). Or possibly they were just easier to write as separate programs (the V7 _expr_ is just [[a single yacc file http://minnie.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/cmd/expr.y]]). Note that there are structural reasons in the Bourne shell to make _if_ et al conditions be the result of commands, instead of restricting them to (only) be actual conditions. But the original Bourne shell could have done this with _test_ or the equivalent as a built-in command, and it certainly has other built in commands. Perhaps _test_ needing to be an actual command was one of the things that pushed it towards not being built in. You can certainly see a spirit of minimalism at work here if you want to (although I have no idea if that's the reason). (This expands on [[a tweet of mine https://twitter.com/thatcks/status/737339907270713349]].) === Sidebar: It's not clear when _test_ picked up its _[_ alias Before I started writing this entry, I expected that _test_ was also known as _[_ right from the beginning in V7. Now I'm not so sure. On the one hand, the actual V7 shell scripts I can find eg [[here http://minnie.tuhs.org/cgi-bin/utree.pl?file=V7/bin]] consistently use _test_ instead of _[_ and the V7 compile scripts don't seem to create a _[_ hardlink. On the other hand, [[the V7 _test_ source http://minnie.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/cmd/test.c]] already has special magic handling if it's invoked as _[_. (There are V7 disk images out there that you can boot up on a PDP-11 emulator, so in theory I could fire one up and see if it has a _/bin/[_. In practice I'm not that energetic.)