Bash or KornShell (ksh)?
I am not new to *nix, however lately I have been spending a lot of time at the prompt. My question is what are the advantages of using KornShell (ksh) or Bash Shell? Where are the pitfalls of using one over the other?
Looking to understand from the perspective of a user, rather than purely scripting.
The various UNIX and Linux implementations have various different source level implementations of ksh, some of which are real ksh, some of which are pdksh implementations and some of which are just symlinks to some other shell that has a "ksh" personality. This can lead to weird differences in execution behavior.
At least with bash you can be sure that it's a single code base, and all you need worry about is what (usually minimum) version of bash is installed. Having done a lot of scripting on pretty much every modern (and not-so-modern) UNIX, programming to bash is more reliably consistent in my experience.
The difference between Kornshell and Bash are minimal. There are certain advantages one has over the other, but the differences are tiny:
- BASH is much easier to set a prompt that displays the current directory. To do the same in Kornshell is hackish.
- Kornshell has associative arrays and BASH doesn't. Now, the last time I used Associative arrays was... Let me think... Never.
- Kornshell handles loop syntax a bit better. You can usually set a value in a Kornshell loop and have it available after the loop.
- Bash handles getting exit codes from pipes in a cleaner way.
- Kornshell has the print command which is way better than the echo command.
- Bash has tab completions. In older versions
- Kornshell has the r history command that allows me to quickly rerun older commands.
- Kornshell has the syntax cd old new which replaces old with new in your directory and CDs over there. It's convenient when you have are in a directory called /foo/bar/barfoo/one/bar/bar/foo/bar and you need to cd to /foo/bar/barfoo/two/bar/bar/foo/bar In Kornshell, you can simply do cd one two and be done with it. In BASH, you'd have to cd ../../../../../two/bar/bar/foo/bar.
I'm an old Kornshell guy because I learned Unix in the 1990s, and that was the shell of choice back then. I can use Bash, but I get frustrated by it at times because in habit I use some minor feature that Kornshell has that BASH doesn't and it doesn't work. So, whenever possible, I set Kornshell as my default.
However, I am going to tell you to learn BASH. Bash is now implemented on most Unix systems as well as on Linux, and there are simply more resources available for learning BASH and getting help than Kornshell. If you need to do something exotic in BASH, you can go on Stackoverflow, post your question, and you'll get a dozen answers in a few minutes -- and some of them will even be correct!.
If you have a Kornshell question and post it on Stackoverflow, you'll have to wait for some old past their prime hacker like me wake up from his nap before you get an answer. And, forget getting any response if they're serving pudding up in the old age home that day.
BASH is simply the shell of choice now, so if you've got to learn something, might as well go with what is popular.
I'm a korn-shell veteran, so know that I speak from that perspective.
However, I have been comfortable with Bourne shell, ksh88, and ksh93, and for the most I know which features are supported in which. (I should skip ksh88 here, as it's not widely distributed anymore.)
For interactive use, take whatever fits your need. Experiment. I like being able to use the same shell for interactive use and for programming.
I went from ksh88 on SVR2 to tcsh, to ksh88sun (which added significant internationalisation support) and ksh93. I tried bash, and hated it because it flattened my history. Then I discovered shopt -s lithist and all was well. (The lithist option assures that newlines are preserved in your command history.)
For shell programming, I'd seriously recommend ksh93 if you want a consistent programming language, good POSIX conformance, and good performance, as many common unix commands can be available as builtin functions.
If you want portability use at least both. And make sure you have a good test suite.
There are many subtle differences between shells. Consider for example reading from a pipe:
b=42 && echo one two three four | read a b junk && echo $b
This will produce different results in different shells. The korn-shell runs pipelines from back to front; the last element in the pipeline runs in the current process. Bash did not support this useful behaviour until v4.x, and even then, it's not the default.
Another example illustrating consistency: The echo command itself, which was made obsolete by the split between BSD and SYSV unix, and each introduced their own convention for not printing newlines (and other behaviour). The result of this can still be seen in many 'configure' scripts.
Ksh took a radical approach to that - and introduced the print command, which actually supports both methods (the -n option from BSD, and the trailing \c special character from SYSV)
However, for serious systems programming I'd recommend something other than a shell, like python, perl. Or take it a step further, and use a platform like puppet - which allows you to watch and correct the state of whole clusters of systems, with good auditing.
Shell programming is like swimming in uncharted waters, or worse.
Programming in any language requires familiarity with its syntax, its interfaces and behaviour. Shell programming isn't any different.
This is a bit of a Unix vs Linux battle. Most if not all Linux distributions have bash installed and ksh optional. Most Unix systems, like Solaris, AIX and HPUX have ksh as default.
Personally I always use ksh, I love the vi completion and I pretty much use Solaris for everything.
I don't have experience with ksh, but I have used both bash and zsh. I prefer zsh over bash because of its support for very powerful file globbing, variable expansion modifiers, and faster tab completion.
Here's a quick intro: http://friedcpu.wordpress.com/2007/07/24/zsh-the-last-shell-youll-ever-need/
For scripts, I always use ksh because it smooths over gotchas.
But I find bash more comfortable for interactive use. For me the emacs key bindings and tab completion are the main benefits. But that's mostly force of habit, not any technical issue with ksh.
Actually, the standard shell is Bourne shell (sh). /bin/sh on Linux is actually bash, but if you're aiming for cross-platform scripts, you're better off sticking to features of the original Bourne shell or writing it in something like perl.
My answer would be 'pick one and learn how to use it'. They're both decent shells; bash probably has more bells and whistles, but they both have the basic features you'll want. bash is more universally available these days. If you're using Linux all the time, just stick with it.
If you're programming, trying to stick to plain 'sh' for portability is good practice, but then with bash available so widely these days that bit of advice is probably a bit old-fashioned.
Learn how to use completion and your shell history; read the manpage occasionally and try to learn a few new things.
For one thing, bash has tab completion. This alone is enough to make me prefer it over ksh.
Z shell has a good combination of ksh's unique features with the nice things that bash provides, plus a lot more stuff on top of that.
Available in most UNIX system, ksh is standard-comliant, clearly designed, well-rounded. I think books,helps in ksh is enough and clear, especially the O'Reilly book. Bash is a mass. I keep it as root login shell for Linux at home only.
For interactive use, I prefer zsh on Linux/UNIX. I run scripts in zsh, but I'll test most of my scripts, functions in AIX ksh though.
Bash is the benchmark, but that's mostly because you can be reasonably sure it's installed on every *nix out there. If you're planning to distribute the scripts, use Bash.
I can not really address the actual programming differences between the shells, unfortunately.
Bash is the standard for Linux. My experience is that it is easier to find help for bash than for ksh or csh.