well, actually Sun doesn't sell much of anything notable anymore. But back when I started playing with Unix, Sun workstations were golden, and SunOS was the standard by which all other Unixes were judged. 4.1.3U1 was rock solid, fast and ran on neat Sparc hardware.
And with it came the cshell. Well, of course it came with the original Bourne shell, but that was just for scripting, right? Surely nobody used that dinosaur interactively, right? Did it even have command history?[1] And ksh - that was like the Scientology of shells[2] - it was always around, but only the kooks used it. Everybody used /bin/csh, because that was just The Right Thing, and there was little argument.
Except, of course, from the ubernerds using tcsh[3]. The arrow keys were useful! It had filename completion! It understood terminfo! It was badass timesaver for anybody who sat in front of a shell all day.
That was over a decade ago, and my login shell is still tcsh. I haven't even thought about it in the last ten years -- meaning I've probably used it more than any other single piece of software in my lifetime[4]. And then, the Linux guy - my former tcsh-using colleague - questioned my choice of interactive shells. He was creating an account for me on some server and realized, "oh, I have to install tcsh so you can login."
What!? It's tcsh, it's the standard... well, maybe that should be was the standard...
% echo $version
tcsh 6.12.00 (Astron) 2002-07-23 (powerpc-apple-darwin) options 8b,nls,dl,al,kan,sm,rh,color,dspm,filec
There hasn't even been a point release in almost four years. Yeah, maybe that's a positive on me being behind the times. So I dusted off my scruffy Unix-guy beard and ran that scary chsh command. After a little playing, here's why I'd recommend you make the plunge and dig into zsh over tcsh:
- Extended aliases
tcshlets you alias a command, butzshlets you alias arguments, too. Global aliases (alias -g) match any position. So you could, for example, work around annoyances with system utilities. On a Mac,/tmpis a symlink, and you rarely want to operate on the symlink, but almost always want to operate on the directory.tar -cf tmp.tar /tmp? Not very useful. Thus:alias -g '/tmp'='/tmp/.'You can also alias file extensions to map to programs to execute. Let's say you have some .NET programs (for example: Vault[5]) as
.exefiles:alias -s exe=monowill let you type
vault.exe, and will executemono vault.exe. Beautiful! - Directory history
Sure, tcsh haspushdandpopd, and they're surpremely handy if you're disciplined enough to actually use them. I've never been that disciplined, and I always end up shooting myself in the foot when I leave the insane depths of a source tree to go into my home directory or/tmpfor a second. Solution?setopt AUTO_PUSHDNow instead of kicking myself for not running
pushd, I justpopdback to where I was before. Handy. - Multi-line history editing
This one's a no-brainer.tcsh's history editing stinks. Do a foreach, make a mistake inside the block, and then try to go back and change it. Nope.zshpops up the entire block. (Heck, evenbashdoes this right.) - Better single line history
Let's say you edit a file in a faraway directory, do a few dozen things and forget where that file was. Intcsh, if you know the line number, you may able to get that faraway path back. Inzsh, if you remember part of it, you're better off:vi /Users/ethomson/tmp/project-1.0/src/libproject/Makefile
...
...
!?Makefile
will search your history for Makefile and bring up the most recent. Want to do something else with that file, instead of running
vi? Try:cat !?Makefile?:1(the first parameter from the matching line.) Or, try:
!?Makefile<TAB>to bring up the whole command from history on your prompt, for editing.
- Smarter shell builtins
It surprises me how often I useforeachto do renames. Backing up a group of files -- or worse, restoring them. Previously I might have done:foreach a ( *.log.bak ) set b=`echo $a | sed -e "s/\.bak$//"`
mv $a $b
done
zsh's builtinzmvmakes this easy:zmv -W '*.log.bak' '*.log' - Math!
Despite majoring in math, I never was very good at arithmetic. But neither istcsh. On the other hand,zshhas math builtin. Let's say I want to add track numbers to some music files[6] intcsh:set cnt=0
foreach a (*)
set cnt=`expr $cnt + 1`
mv $a $cnt-$a
endBut in
zsh:cnt = 0;
for a in *; do
mv $a $((cnt=cnt+1))-$a
done(Okay, so you only save one line, but you also don't have to remember that
exprhas such a broken tokennizer that it can't understand the difference between "0+1" and "0 + 1"
I'm very pleased with zsh. Even if its improved history, better aliasing and better directory traversal only shave a little bit of time off my shell usage, that adds up over the course of a week - and maybe it makes me a little less grouchy[7]. In the little bit of time I set aside for learning new zsh features, I found the the zsh wiki to be super-helpful.
- No
- Sorry Jeremy... ;)
- Nobody I knew had ever heard of bash until those crazy first Linux distributions came out, at which point its familial heritage was called into question on several occasions.
-
viwould be first if it weren't for the transition to nvi in 4.4BSD and the widespread adoption of vim by linux distributions (despite its incorrect undo syntax.) - You'd be correct if you recognized this as shameless corporate promotion.
- Globbing the filenames with
*will obviously only work if the filenames are track-ordered. For the purposes of this example, let's assume filenames are song names and the album's tracks are in alphabetical order. This isn't completely contrived: see the excellent (and alphabetical) The Magnetic Fields: i. - My co-workers may, of course, disagree...
Nice post - it's left me hankering for UNIX again after moving to .NET. But I'm surprised nobody you met had heard of bash before Linux. How come a UNIX guy has ended up working with Mac OS ?
I'm not entirely sure how we missed bash, to be honest with you.
In the early '90s, I worked two places - doing lightweight development in a scientific institution that had a gnarly mix of operating systems, and then doing system administration at a software shop that had an insanely heterogenous mix of Unixes. Both places were very SunOS heavy -- the Suns were the desktop of choice, and did all the heavy lifting as servers. Thus, a huge bias towards SunOS (pre-Solaris), and BSD in general. (Thus our bias toward csh and its offspring tcsh.)
So, until we started playing with Linux at home, we'd never seen bash. I suspect one of us accidentally hit the up arrow, realized history completion worked, and flipped out and dug in to figure out what was going on. Thus, our discovery of bash.
Eventually, Slackware Linux was released and we carefully started rolling out Linux workstations. Soon, the kernel's network and SCSI drivers became reasonably stable, and we started rolling out servers. Within just a few years, Linux displaced SunOS for both desktops and servers.
As far as the MacOS goes, at that same software shop, we had a NextStep version of our software. So, one day I ended up with a NeXT on my desk. (An old slab, if I recall.) I loved it -- the aura around the NeXT was mostly deserved. I loved it so much that I ended up buying an old NextStation Color at home that I can't bear to part with.
OS X is a solid continuation of that -- Unix under the hood, and a solid UI on top. Screw GNOME and KDE -- I'm surprised more old Unix geeks aren't taking the plunge.
If you do ever get "stuck" running a tcsh again, it also supports that command history searching, and if the searching doesn't work for you, the "history" command will display the entire contents of the command history, with numbers.
Hi Greg-
Thanks for the comment! To be fair, I still have been using a lot of tcsh, since it's still (mostly) uniquitious on my computers. And, of course, it's still great.
Enlighten me on history searching -- I know you can get better history expansion with:
set autoexpand
bindkey -k up history-search-forward
bindkey -k down history-search-backward
Then you'll be able to start typing a history command, and hit tab for completion, then use up and down for other matches with that prefix -- but is there a setting that searches substrings?
...Sure, tcsh has pushd and popd, and they're surpremely handy if you're disciplined enough to actually use them. ...
You could alias cd to pushd or if you want to be drastic, rename cd and symlink cd to pushd. Not a elegant as just using cshell but it works for those of us who don't have time to relearn a whole new shell at the moment
All right, Troy, after embarassing me in my Mac post, and pointing out that I'm perhaps prone to hyperbole, I feel compelled to point out that cd is a shell builtin, and thus can't be symlinked.
Take that! ;)
And what kind of a Mac guy are you if you're not down with the hyperbole? ;)
Damn... well with bash you could do this:
function cd() { command pushd "$@";}I'll have to get back to you about tcsh. I'll take .500 though