top | item 3533895

Zsh is your friend.

167 points| mgrouchy | 14 years ago |mikegrouchy.com | reply

108 comments

order
[+] LeafStorm|14 years ago|reply
While from what I have read about it zsh is a nice shell, it doesn't deal with what I find to be the biggest problem with bash, sh, and just about every shell that isn't fish: the horribly ugly and inconsistent syntax. And I think it's rather sad that on what is supposedly the most advanced shell of our generation, you still have to deal with a thousand ridiculous redirections and quoting styles, different delimiter keywords for every control structure ("fi?" "done?" "esac?" Why not just freaking "end?"), and rules for expanding variables that come back to bite you in the rear whenever you have spaces, quote characters, or anything besides a run of letters, numbers, and a select few punctuation marks in your filenames or other variables.
[+] ramLlama|14 years ago|reply
I have been using fish for several years now. It's community is a fraction of zsh, bash, and others, and I've tried to go back to them, mostly out of misplaced "everyone else is doing it" mindset

Fish is a great shell. It's a modern shell, that uses colors, UTF, and processing power that didn't exist when the others were designed. I feel the best thing about it is the sane defaults and large number of prebuilt completions. For any other shell, I have to dive into bashrc's and esoteric commands to get what I want. Fish just does what I want. It's made me far more productive, and for that, it gets my best shell award.

Its scripting support is good, very similar to other shells. Yes, the syntax is non-compatible, and not even POSIX. But, it makes more sense. Besides, for anything except the simplest of scripts, I use lua. I doubt you'd want to use bash to do something very complicated.

Some people want their shell scripts to be compatible and do a lot of cool things. I feel that the days of a shell being used for scripting are past. For me, a shell is a way of interacting with the system. Fish does this really well. Scripting is a slight afterthought, as it should be.

[+] kruhft|14 years ago|reply
Once you learn the zen of shell script, like any programming language, those problems pretty much go away. Shell script is a tiny language packed with features and can be learned through constant use in a week, but like any language, it takes time to master.

It's incredibly powerful for interactive use and data manipulation combined with the standard Unix tools and sometimes pulling out perl or python is more work than just banging out a pipeline on the command line.

Quoting does take some time, but just remember that when in double to quote your variable expansions with double quotes. There's more too it, but that's a good rule to start with.

[+] jff|14 years ago|reply
Try Plan 9's "rc". It has a more C-like syntax, so you write things like "for (i in `{seq 1 100}) { echo $i }"; I really enjoy writing in rc.
[+] bwarp|14 years ago|reply
You've obviously never used PowerShell then if you think *sh are horrible ugly and inconsistent!
[+] Lewisham|14 years ago|reply
The thing I like about fish is the easy history nav. I type "git" and press Up, and I get to go through my history of anything that started with "git" very quickly. I'll often remember I typed an svn command three weeks ago, but forget the parameters, and I'll have it back within 15 seconds.

It's like magic!

[+] adavies42|14 years ago|reply
the problem is there are really two things that most shells are trying to simultaneously optimize for--interactive and scripted use. sometimes these conflict in annoying ways--i think the main reason arrays are so obnoxious to use in bash is that their syntax collides badly with glob syntax.

some shells that make excellent script languages are terrible for interactive use--a stock ksh, even ksh93, is pure torture for someone who grew up on bash and zsh and expects completion, history, a nice prompt, decent command editing, etc.

(i'm not sure if the reverse is precisely true, though certainly there are interesting programming features in ksh that are absent in zsh--discipline functions and so on.)

[+] googletron|14 years ago|reply
I think your complaining more about shell scripting rather than the terminal use itself.
[+] bryanlarsen|14 years ago|reply
- I'm using bash on Ubuntu. When I type "kill <tab>" I get a list of process numbers, not the list of files in my current directory as you imply.

- shared history sounds like a bug, not a feature. I have long lived terminals open, each dedicated to a specific purpose. Shared history would intermingle them.

- typing `gut` in bash gives me:

    No command 'gut' found, did you mean:
     Command 'cut' from package 'coreutils' (main)
     Command 'get' from package 'code-aster-run' (universe)
     Command 'gout' from package 'scotch' (universe)
     Command 'git' from package 'git' (main)
     Command 'gpt' from package 'gpt' (universe)
     Command 'gst' from package 'gnu-smalltalk' (universe)
You're batting 0/3. Certainly there must be some advantages to ZSH, but you haven't listed any yet.

(Note that I didn't have to configure any of this. Ubuntu probably did, but I didn't).

[+] masklinn|14 years ago|reply
Fwiw on #3, it's not the same at all.

1. Your feature comes from Ubuntu, not bash

2. More importantly, in ZSH if the correction is accepted by the user the command gets executed (with the fix) without any manual redoing. The correction can even be made permanent for frequent typos.

(and while I like ZSH a lot, shared history does tend to be a pain in the ass for me)

[+] thenduks|14 years ago|reply
How about the fact that zsh enforces that you spend a certain amount of time per day just contemplating your existence:

    % time zsh -c exit
    zsh -c exit  0.22s user 0.21s system 97% cpu 0.436 total
    $ time bash -c exit
    bash -c exit  0.00s user 0.00s system 83% cpu 0.004 total
Typing too early will just blackhole your keystrokes, of course, so no cheating!

Or how about how when using an RPROMPT it makes copy/pasting stuff out of the terminal infuriate your IM buddies?

:)

Actually these are downsides, let's try fish instead, maybe?

    % brew install fish
    % fish
    zsh: correct 'fish' to 'vis' [nyae]? GRRR
[+] gcv|14 years ago|reply
Shared history in zsh is essential to my workflow. I also keep many terminals open, and while I do separate them by task, I often just pick one which happens to be in the right directory and start typing away. I always search through history using Ctrl-R, and almost never use up-arrow cycling. Shared history makes this work seamlessly.

This is obviously configurable, so if you prefer a different workflow, zsh will accomodate it.

[+] Symmetry|14 years ago|reply
In fairness to zsh, "kill <tab>" just lists the number rather than giving the names. In zsh or fish, by contrast, you get the process name too.
[+] sandGorgon|14 years ago|reply
about the 3'rd thing, that's not a bash thing - that's a ubuntu thing, which nicely integrates with bash by default. You could get the same thing by putting

function command_not_found_handler() { /usr/bin/python /usr/lib/command-not-found -- $1 }

in your .zshrc

P.S.

[+] icebraining|14 years ago|reply
Your third example is not the same. Does Bash correct it for you, or just lists similar commands?
[+] pmr_|14 years ago|reply
He also doesn't hit the mark on editing modes. Emacs and Vi keybindings for shells are usually provided by libreadline.

I was really looking for a different shell before. But if those are zsh killler features, it certainly wont be my choice.

[+] ohgodthecat|14 years ago|reply
Shared history can be either a burden or a godsend, I like it but I usually just end up using whatever basic bash shell I'm on without a custom config as most of the things I do are remote.

The zsh autocorrect works much differently than what you have given. You have shown a feature of ubuntu (and probably debian) that looks for packages matching/close to your given command but what zsh does is give you, depending on your chosen settings, full autocorrect.

Where you may be able to type gut status and get No command found the setup in zsh would allow either for gut status to be autocorrected to git status or would ask you if you meant git status while waiting for a confirmation.

[+] jgrahamc|14 years ago|reply
I like zsh. Probably my favorite feature is that it will autocomplete paths/filenames in an scp command on the remote end if authentication is done with keys.

Also you can do stuff like /u/l/b and hit TAB.

[+] riobard|14 years ago|reply
Probably my favorite feature is that it will autocomplete paths/filenames in an scp command on the remote end if authentication is done with keys.

This is possible in Bash too with bash-completion.

[+] Wilya|14 years ago|reply
Funnily enough, I find that the autocorrection tends to get in my way more often than not. Being prompted if I meant 'git' when I type 'gut' interrups my thinking flow, while 'command not found' doesn't. And the autocorrect is very bad for cp/mv ('mv test test1' will likely ask me if I meant 'test' instead of 'test1').

That being said, I'm a happy zsh user, for all it provides. Autocorrection is just one of the only things that, in my opinion, don't work well, so it's strange to market them.

[+] babs474|14 years ago|reply
Is anybody else addicted to shell mode within emacs?

I love having the shell as just another buffer right in the editor. Easy history searchability, copy and paste between code and various repls or SQL prompts, and all the other full editor features available at the prompt.

[+] drothlis|14 years ago|reply
I like the idea, but I'm too used to bash's autocompletion (the Emacs-provided autocompletion is similar but not quite the same), the autocd option, CDPATH, etc. And changing directories in the shell with anything other than cd (pushd, or an alias or script) confuses Emacs's directory completion.

The last couple of days I've been trying terminal-mode rather than shell-mode, and it works much better. Many standard Emacs keybindings get remapped though.

[+] jroes|14 years ago|reply
I used to use oh-my-zsh but gave up on it after a few months because it took almost 20 seconds to open up a Terminal tab. I switched back to bash with some really basic git completion and was happy enough, enjoying < 2 second opening times.
[+] arghnoname|14 years ago|reply
my tabs open up immediately but it does take a little while to log in, which really is annoying. I think depending on how you configure things you can move where and how often the wait occurs and by disabling certain things, how long it is.
[+] steder|14 years ago|reply
+1 for actually giving me a couple reasons to try zsh. Of course I'd be surprised if many of these features aren't already hacked into some bash guru's dotfiles but, that said, more autocompletions without writing them myself is always nice.
[+] RyanMcGreal|14 years ago|reply
The supremacy of bash over zsh &c. seems to be an excellent case study in the "Worse is Better" hypothesis.

http://www.jwz.org/doc/worse-is-better.html

[+] Symmetry|14 years ago|reply
Not really, you're not seeing bash have many more features because its simpler on the inside at the cost of sometimes breaking. Rather, it seems an example of " the most dangerous enemy of a better solution is an existing codebase that is just good enough"
[+] adavies42|14 years ago|reply
my favorite zsh feature is advanced globbing--i'd far rather type

    ls -d ***/*(/)
than

    find . -follow -type d -exec ls -d {} \;
[+] graywh|14 years ago|reply
FYI, the (/) is called a glob qualifier.
[+] heresy|14 years ago|reply
I agree, though I'd probably suggest working from a simple zshrc for starters ("man zshall" is also your friend).

I just spent a bit of time yesterday tweaking information in my prompt just so:

http://imgur.com/OSEB3

And it's made a huge quality of life difference to what I had before.

Worth spending a bit of time making your shell environment optimized for yourself though, and not just copying someone else's setup, in my opinion.

You spend a lot of time there, programming for UNIX, why not make it rock?

[+] nickolai|14 years ago|reply
I used to use a lot of zsh at work, and one thing that drove me nuts was overzealous wildcard expansion.

  >scp server2:~/folder/* .
zsh: no matches found: server2:~/folder/*

nothing in current work dir matches 'server2:~/folder/ * ', so zsh helpfully yells at me. yeah I know use single quotes to avoid expansion, and backslash should work too. It makes total sense because * is a reserved character, but still, bash got it. surely Zsh could've too ?

It probably got fixed since then, but this raw frustration is my most vivid memory from zsh usage.

[+] satiani|14 years ago|reply
This behavior can be turned off by adding this to .zshrc:

  setopt no_nomatch # if there are no matches for globs, leave them alone and execute the command
zsh also tries to autocomplete directory names using variables in global namespace that point to directories. I found that behavior maddening and can be turned off with:

  setopt no_cdable_vars # don't use named directories in cd autocompletion
[+] tux1968|14 years ago|reply
This article inspired me to give zsh a spin. The pre configured setup of oh-my-zsh is a nice starting point.

But am really missing the Bash "help" command, and the combined (easily searchable) man page.

Thus far I have not been able to figure out which feature or config option to disable to stop this annoyance:

$ grep vim

zsh: correct 'vim' to '.vim' [nyae]?

Please don't "help me", i typed exactly what I wanted.

[+] skeletonjelly|14 years ago|reply
Care to post your .zshrc?

Edit: I have setopt correctcall and I do not get this behaviour.

On an unrelated not, this is a classic example of complaining about why a product doesn't work and having users jump at the chance to fix your issue to prove it's worth.

But how to monitize this... :)

[+] mgrouchy|14 years ago|reply
unsetopt correct_all

in your .zshrc

also run-help , I believe is the zsh equivalent to the Bash help builtin.

[+] xegroeg|14 years ago|reply
Bash can also do shared history:

  export HISTCONTROL=ignoredups
  export HISTCONTROL=ignoreboth
  HISTSIZE=50000
  shopt -s histappend
  PROMPT_COMMAND='history -a'
  #history search inline
  #bind '"\e[A": history-search-backward'
  #bind '"\e[B": history-search-forward'
[+] bsagert|14 years ago|reply
Thanks mgrouchy for another site that breaks pgdn. The header that never moves hides some lines on the next page. Reading becomes an annoying series of page downs then scroll up a bit to read the hidden sentences. Does this annoy anyone else?
[+] mgrouchy|14 years ago|reply
Hey, thanks for the feedback, I just recently changed the look of the blog after about a year of neglect. Its actually just Twitter Bootstrap(1.4). I never use page down or up so I completely missed the problem. I will see if I can find a workaround. Thanks again!
[+] tlvince|14 years ago|reply
If you're looking for the "keyboard navigable completion list", this what you want:

    zstyle ':completion:*' menu select
[+] ilaksh|14 years ago|reply
I tried that and about a million other things in Ubuntu. When I hit tab I see options, but nothing I put in my .zshrc will allow me to use the arrow keys or anything else to navigate the completion list.

I am using oh my zsh but I tried turning it off and it didn't seem to matter.

Maybe only Mac users use zsh?

[+] skeletonjelly|14 years ago|reply
I wish the author had put the settings used to get those effects. Unless they are default? It's probably just formatting?
[+] mgrouchy|14 years ago|reply
some of them are the built in oh-my-zsh things, but I added some of the settings in the posts comments for people who asked.

Is there something particular you are looking for?

[+] mobjedgar|14 years ago|reply
This is incredible. I'm converted!
[+] jfmercer|14 years ago|reply
bash's spy equivalent in Jason Bourne. zsh can't compete with that.