The Z Shell And Why You Should Be Using It

I've only recently come to appreciate the glory that is zsh, a command line shell with an arsenal of features large enough to keep you learning for the rest of your natural lifetime. I made the switch from bash (seems to be the most common default shell on Linux) a few years ago after reading somewhere of zsh's vast benefits. I spent a couple days learning the ropes, assembling a basic .zshrc and memorizing a few tricks, then moved on to using those daily and forgot about it. I was asked recently why I used zsh and became aware I had no idea anymore, everything I used had just come to be part of day to day life. Since starting with Red Hat however I'm logging into dozens of temporary Linux systems that are frequently rebuilt for testing, always reverting to the standard Bash shell. Suddenly I'm all too aware of the few zsh features I've come to love.

I'll start with a link to my zshrc (I'll try to update this file as I update my own copy) before moving on to the features I'm most fond of.

I can't emphasize enough how little I know about zsh. I'm very serious when I say I've barely scratched the surface, I learned the basics of how to get around, picked up a couple cool little features, and left it at that. As such I'm by no means claiming to be an expert, only hoping to sway any potential console ninja's out there to check it out. I'm also not sure how much of this functionality can be mirrored with bash.

By far the feature I miss the most is the searchable command history. Using the provided zshrc, I can start typing a command and do ctrl+p (backwards) or ctrl+n (forwards) to recall commands I last entered starting with the text I've typed so far. When you're doing a lot of work on the command line, the up arrow is obnoxious to use for searching when you need to move back a ways but know exactly what you're looking for. If working over remote ssh, the lag factor makes things even more error prone and irritating.

Zsh also features intelligent tab completion. I honestly don't know how this works in a timely fashion, but more often than not when you're hitting tab on an argument to a command, zsh knows what's valid and what isn't. This can be as simple as knowing you're looking for a directory when typing cd mydir, or as advanced as auto-completing available packages for apt-get install, ant build.xml targets based on the build.xml in the current directory, etc.

Both Bash and Zsh feature a directory stack (pushd and popd) for jumping back to directories you previously visited. It's likely you can do this with Bash as well, but zsh allows for automatically pushing onto the stack every time you change directories. dirs -v (aliased as just "d" in my zshrc) prints the current stack, cd ~# takes you there. Substitute any command you like for cd. I keep zsh configured to assume I meant to cd anytime I enter a directory name (alone) on the command line as well.

Global aliases are strings that are expanded anywhere on the command line. Setup with alias -g, see the zshrc link for examples.

Suffix aliases tell zsh to execute the following command when you just enter a filename on the command line, based on that files extension. (alias -s)

That pretty much covers the sort of core every day features I came to love in zsh. Before writing this post however I set out to do some more reading for the first time since I started with zsh and see what new tips and such were out there. I found a ton, here are a few of the gems I picked up today.

Using the history command, pick off the number of a command you're interested in. !42 executes command 42 again. !42:s/foo/bar/ replaces all occurrences of foo with bar and executes. You can press tab before return to see the results before you ship it.

When editing a command line, !#:0 expands to the command, !#^ or !#:1 to the first parameter, !#:1-4 to the first four parameters, !#$ to the last parameter, or !#* to all parameters. I'm not certain yet how useful these will be, but I'm making an effort to find out. The # in the above expressions always indicates the current command line. I believe leaving it out defaults to the previous command, and using a number should operate on a history command. See the links at the end of this article for more.

Start typing a filename, press ctrl + d to see completion options anywhere in the path. (zshrc configured to have this happen after pressing tab twice when trying to auto-complete)

vim **/file.py will find file.py anywhere below the current directory and open it.

That's about all I can think of right now, but please feel free to post any beloved zsh tips in the comments. I plan to read and re-read zsh tip documents now and then in the future and keep adding new tricks to the arsenal, perhaps updating this post as they come.

Further Reading

The Z Shell
Best of Zsh Tips
Zsh Lovers
Zsh Command Prompt

UPDATE: The Bash Shell And Why You're Already Using It: Bowes takes the time to investigate these features and finds almost all of them available in bash.

UPDATE: Bashing Bash or: How I Learned to Stop Worrying and Love Zsh: More response to this post from a fellow zsh'er.