What are the fundamental differences between the mainstream *NIX shells and what scenarios might prompt you to use one over the other? I understand that some of it probably comes down to user preference but I've only ever used bash and I'm interested to hear where another shell might be useful.

Also, is there an impact on user-written shell scripts when running under one shell or another or is it simply a matter of changing the shell at the top of the file? My instinct says it's not that easy.

5 Answers
5

For interactive use, there are two main contenders, bash and zsh, plus the straggler tcsh and the newcomer fish.

Bash is the official shell of the GNU project and the default shell on most Linux distributions. On other unices that don't ship with a decent interactive shell as part of the base installation, I think bash is what people tend to choose, in a self-reinforcement “bash is everywhere so I'll use it too” loop. See also Why is bash everywhere? (with a lot of historical information).

Tcsh was once (up to the early 1990s) the shell with the best interactive features, like its predecessor csh. That made it popular for interactive use (but not for scripting). Zsh caught up with tcsh and fairly quickly improved further, and bash caught up (with programmable completion) in the early 2000s, while tcsh has barely made any progress in the past 15 years. Therefore there is little reason to learn tcsh now.

Fish tries to be cleaner than its predecessors. It has some neat features (simpler syntax, syntax coloring on the command line) but lacks others (whatever the author doesn't like). The fish community is a lot smaller than even zsh's, making the effects even more acute. See also What are the differences between fish and zsh ?.

For scripting, there are several languages you might want to target, depending on how portable you want your scripts to be.

Anything that pretends to be Unix-like has a Bourne-derived shell as /bin/sh. There are still some commercial unices around where /bin/sh is not POSIX compliant.

Almost every now-running unix has an sh executable that is at least compliant with at least POSIX.2-1992 and usually at least POSIX:2001 a.k.a. Single Unix v3. This shell might live in a different directory such as /usr/bin/posix or /usr/xpg6/bin. POSIX emulation layers also exist for just about every system that's powerful enough to support it, making it an attractive target.

Many unix systems have ksh93, which brings some very useful features that POSIX sh lacks (arrays, associative arrays, extended globs (*(foo), @(foo|bar), …), null globs (~(N)foo*), …). Ksh was initially commercial software (it became free in 2000, after some habits had set), and many free unices (Linux, *BSD) got into the habit of only providing a much older free clone (pdksh) lacking many of these useful features. Pdksh is now getting displaced by mksh outside of OpenBSD, but even mksh falls short of implementing all ksh93 features. Today, you can't count on ksh93 being available everywhere, especially on Linux where bash is the norm.

Bash is always available on Linux (except some embedded variants) and often on other unices. It has most of ksh93's useful features, though sometimes with a different syntax.

Zsh has most of ksh93 and bash's useful features. Its core syntax is cleaner but incompatible with Bourne. Except for Apple OS/X, don't count on zsh being available on a system you didn't install.

For more advanced scripting, you can turn to Perl or Python. These languages have proper data structures, decent text manipulation features, decent process combination and communication mechanisms, and tons of available libraries. Most unix systems have them, either bundled with the OS or installed by the administrator (because there are so many Perl and Python scripts out there that it's a rare system that doesn't have at least one of each).

For scripting I target dash, (unless I need the advanced features of bash) which has a minimal feature set, and is posix complaint for maximum compatibility. (and it is small light and fast)
–
hildredJul 11 '14 at 21:10

Great documentaion! Two notes. First, Solaris is one of those "commercial unices around where /bin/sh is not POSIX compliant." Specifically, it uses jsh (which is not a java shell!), which lacks variable substitution like ${VAR#foo} and ${VAR%bar}.
–
Adam KatzJan 15 at 16:00

Second, tcsh is rather popular among UNIX users who learned their tricks before the ~mid-90s (which saw the introduction of both bash and zsh), especially among the older UNIX + C developers, who started life with csh (reminder, the c in csh stands for the C language, which was the inspiration for its differences from bourne-style shells). See also Csh programming considered harmful, which I often use for tips on POSIX deep magic (in addition to its anti-csh arguments).
–
Adam KatzJan 15 at 16:05

There are two basic flavors of shell, sh (e.g., bash) and csh (e.g., tcsh). For interactive use, it mostly comes down to what you are used to. I've used csh, and then tcsh, for years and it would be painful to switch, just because I'm so used to it. I've used bash as well, and I don't think there are any compelling reasons to switch. Except maybe if one or the other is not available on machines that you regularly use.

For programming, the syntax is different. You can't just change the shell, but need to change the syntax of the script as well. For scripting, you want to use sh or bash. The syntax is much more amenable to scripting, as explained here (thanks to Riccardo Murri for the link. The is a good guide on bash scripting.

If you haven't decided on a shell, and you expect to write some scripts, I would use bash just to reduce the amount of things you need to learn.

Back in the old days, when AT&T invented UNIX, there was Bourne Shell, written by Steve Bourne. It was pretty basic, and lacked a lot of tools we take for granted nowadays.

AT&T wasn't really in the UNIX business, so at this time the very basic OS was adopted somewhat by Berkelely, and they made some changes into BSD UNIX. Among many changes, was a new shell, called csh, which had a lot of improvements over sh, including job control better interactive use and so on. Unfortunately, they decided the sh programming syntax sucked and created their own, (somewhat badly) copied from C coding styles. (A classic rant is http://www.faqs.org/faqs/unix-faq/shell/csh-whynot/) So now there were two syntaxes.

Later, they made improvements to CSH adding tab completion and some other things. This became tcsh, and if you use CSH, this is probably the one you use.

AT&T decided it wasn't totally out of the UNIX business, and they polished it up too. David Korn (nice guy) created the Korn shell. Based on the idea of extending Bourne shell syntax, it added a lot of things for both programmers and interactive use. There are actually a few versions, and you may rarely see things like ksh88 and ksh93, denoting the variants.

Then came FSF and the GNU OS. They wanted to make their own UNIX-compatible OS named the Hurd, and wanted a better shell for it. They called bash, for Bourne Again SHell. POSIX rules came in just around this time, and they wanted to make the POSIX shell. They looked around, taking the syntax from Bourne shell and the improvements from Korn shell, plus stealing and extending the interactive features from tcsh. It became the de facto shell on Linux, so it's very common.

There's also the zsh, written to be the 'ultimate' shell. It's also very common in the Linux world. It extended bash (and cross pollinated a bit, some new things went back to bash).

If i were to pick a shell, I'd pick bash or zsh. bash is possibly in a few more places than zsh. zsh is more powerful, but bash has been fine for me.
Real /bin/sh Bourne shell is around just for historical reasons. bash has pretty much all that ksh has to offer and more. The syntax is cleaner than csh or tcsh, and has better features than either one of them.

To convert a script depends on from what to what. Bourne shell style (sh, ksh, bash, zsh) to or from csh style (csh, tcsh) will be hard. Going from old to newer (/bin/sh => bash, /bin/ksh => zsh) will be easier than the other way.

Do note that the csh-whynot page was written back in September 1995 (check the version tag at the top). I don't know, but I would expect lots of things to have changed in the 18 years since then.
–
Michael KjörlingJun 29 '13 at 19:28

I've used numerous shells over time. Not anything super advanced but lots of practical sysadmin and programming stuff which has required enough customization.

I think zsh has more customization options, at least it used to, but after using it for quite some years I had enough with its stability and character encoding issues. Bash is rock solid, never had similar problems and it is installed everywhere.