also see
ZshTricks
Read the man pages. None of this is secret or undocumented shit, it's just that it's a challenge to find the stuff that's actually easy to fit into your daily routine. So that's what I'm gonna concentrate on, stuff that actually helps on a daily basis.
My theory is that syntactic shortcuts -- like the nullcmd redirections, or = expansion, aren't just cute little tricks. If they represent a common idiom, you can internalize the syntax, and you'll come up with better and easier ways to combine these idioms than you would if they were harder to type and read. A shortcut is created because it represents a common thing to do, and if you recognize the idiom and think of it as a basic building block it increases your ability to compose. Idioms. I hate tech writing.
- (zshparam) Set up your prompt. Use a right prompt. Prompts -- left and right -- accept a language with escape codes starting with % which is documented in zshparam(1) under Prompt Expansion. This is because the contents of all magic variables are documented in zshparam(1). This is a general rule. Learn it, and quit complaining about how you don't know what the escape sequences are. Stupid. OK, it's actually in zshmisc(1). Anyway, the advantage of right prompts is that they get out of your way automatically. So if you start typing and you enter the region of the command line where the right prompt is, it just disappears. This makes it good for stuff like current working directory, because if it's in the left prompt and you're in a deep directory, you would otherwise sacrifice the whole line to prompt.
- (zshparam) Bracket your prompt with %B and %b to set it off visually from command output. Use %# instead of %% or, for god's imaginary sake, %(0#,#,%%). Again, if you don't know what I'm talking about, read about Prompt Expansion. In zshmisc.
- (zshparam, zshoptions) If you have to keep track of a bunch of different working directories, put their names in variables and then use the syntax cd ~variable (instead of cd $variable). The ~ enters it into a special hash table of variables that can be used to shorten the name of your current working directory in your prompt, if you use %~ in your prompt. Which you should. In your right prompt. For example, /net/eloi/home/someguy/perforce/oldbranch/src/gibble/gabble/gone could become ~GABBLE/gone in your prompt. AUTO_NAME_DIRS makes it so you don't need to use the ~variable notation first, all path-like variables are considered when shortening the cwd.
- (zshparam) Add something like %(0?,,<%?> ) to one of your prompts. I put it on the right. If the status of the last command was non-zero, it prints it.
- (zshzle) Command-line editing -- by default the shell uses emacs-like commands to move around and edit the command-line. You can switch to vi-like commands with bindkey -v, which is great if you want to confuse people who try to type in your shells. Or if you like vi.
- (zshzle) Quick interactive history searches: history-incremental-search-backward and history-beginning-search-backward are essentials. The former does an emacs-style isearch through history, where you keep typing and it shows you the best match to what you've typed so far, updating every time you press another character. It's instant and it's sweet. For more information, such as how to bind it to a key, read zshzle(1), which is where all this command-line stuff is documented. It's more powerful and safer than !prefix matching. If you also set up zsh to save your history when the shell exits (SAVEHIST, HISTSIZE, HISTFILE in zshparam, extended_history and append_history in zshoptions), you can pretty much get by without aliases or shell functions, just whipping out commands from your gigantic history and editing them.
- (zshzle) If you're in the middle of a command and you realize you need to do something else first -- make the directory where you're storing the logfile, whatever -- hit the key for push-line-or-edit, which is Esc Q by default. Your current command line will disappear. Type your other command, and hit enter. The previous command-line will reappear in the command-line buffer where you can look it over, edit it, and execute it.
- (zshzle) Bind insert-last-word to a key. It's good because often the last word is the file you're operating on, and you'll want to do something else to it.
- (zshzle) The command-line editor is aware of when a command starts and ends, and will load the entire multi-line construct into the buffer and let you move up and down through it. This is excellent for shell functions or complex loops.
- (zshzle, zshbuiltins) Use "vared -c" instead of read, and the user will be able to use command-line editing. Rebind ^M and ^J to self-insert and ^X or ^D to accept-line, and the user will be able to use multi-line command-line editing, like as if in an editor, but without leaving the cozy shell.
- (zshoptions) If you setopt autocd, typing the name of a directory will cd to it. I only include this because that just seems like the right way for the shell to act. That's what should happen when you run a directory, right? Anyway, this creates a number of handy shorthands: .., /, ~. Too bad - does something else.
- (zshexpn) The history expansion modifiers let you do all kinds of things to variables containing file names and glob patterns. Basename: $f:t (t for tail). Dirname: $f:h (for head). Change extension: for f in *.jpg; mv $f $f:r.gif (:r for root, aka strip off the extension).
- (zshbuiltins) You can set a flag on array variables that removes duplicates automatically. This is useful for keeping the length of your path under control. typeset -U path.
- (zshbuiltins) typeset can do anything. You can set a flag on a variable to make it output in hexadecimal, or all lowercase. You'll notice in zshbuiltins that most commands that act on variables are equivalent to typeset plus some switches.
- (zshbuiltins) path and PATH are tied variables. path is an array; PATH is a colon-separated scalar. Assign to one, and the other is updated to reflect the change. manpath and MANPATH are another tied pair. You can create new tied pairs by using typeset -T. For example, typeset -T ld_library_path LD_LIBRARY_PATH. This is useful in conjunction with typeset -U.
- (zshbuiltins) cd - goes back to your previous working directory. Like popd, except you don't have to use pushd or the autopushd option.
- Redirection without a command acts as if you told it to use a builtin version of "cat", more or less. > file will let you create file by typing on stdin and then hitting EOF. < file will dump the file to the screen. Since you usually want a pager when you do this, there's a variable for that: READNULLCMD. If it's "less", then < is equivalent to less.
- (zshoptions) setopt autopushd makes every cd do a pushd, so you have a stack of all the previous directories you've been in, which you can access with what I find to be extremely unintuitive numeric references, and a "dirs" command that shows the stack but not what references to use into it. You can use the pushd_minus option to make it even harder to guess what will happen when you use a numeric reference.
- (zshexpn, Filename Expansion) ls -ld */ -- lists all directories. ls /etc/**/*(.) -- list all files anywhere under /etc. Etc.
- (zshoptions) setopt correctall, and if you type the name of a command wrong, zsh will catch it and usually suggest the right command. It does it for filename arguments as well.
- (zshbuiltins) This isn't really zsh-specific, but the : command is handy for all kinds of things, just by virtue of having no output and being short. Truncate or create a file: :>file. Send an empty message to gale: :|gsend.... Put a > at the beginning of every line of a file: diff <(:) file
- (zshbuiltins) whence is the master version of type and which. If you look in zshbuiltins, which and type are always described in terms of whence. Among its handy options are -m, which lets you find any commands matching a pattern. whence -m '*scsi*'
- (zshmisc) cmd<<<blah is like echo blah | cmd, except it's all internal to the shell, and it's a couple of characters shorter.
- (zshbuiltins) print is to echo as whence is to which as typeset is to half the builtin commands. print -P lets you use prompt escape sequences, which is an easy way to get bolding and underlining. print -l prints each argument on its own line, which is good for http testing with netcat: print -l 'HEAD / HTTP/1.1' 'Host: yammer.net' '' | nc ofb.net 80
- (zshexpn, Filename Expansion) If I see you typing `which command`, I'll find the system you're on and delete your account. You want to use the = prefix. It does the same thing, except right -- if ls is an alias to 'ls -F', which it is for many many people, `which ls` will result in "ls: aliased to ls -F" being expanded, which could conceivably do bad things and will certainly give you a nonsensical error message. There are a number of idioms using this that become easier to wire into your brain if you use the = syntax:
- file =true -- is true a shell script or a binary?
- <=true -- it's a shell script, let's look at it
- rpm -qif =pgrep / dpkg -S =pgrep -- what package did that come from again?
- chmod +s =time -- leave yourself a backdoor.
- =print blah.ps -- use the external command print instead of the builtin; same as "command print blah.ps" except, obviously, easier to type
- EDITOR==vim -- etc.
The relevant part of my dot-files dealing with command-line editing:
bindkey -v
bindkey '^e' insert-last-word
bindkey -a q push-line-or-edit
bindkey '^x' history-beginning-search-backward
bindkey '^r' history-incremental-search-backward
Other tips:
- People switching from bash always complain when they realize that the prompt always goes in the left column, even if the last line of the last command's output didn't end with a newline. These people can be pacified by telling them to setopt nopromptcr, but I can't stand that option myself because it interferes with my right prompts.
- Never set any of the CSH_JUNKIE options. The zsh versions are always better.
- You can't write an alias that does stuff with its arguments, like you can in csh, but you can write a shell function, which is syntactically far less gross. It's at least as easy to write a short shell function, and it's much easier to write a long one than it is to write a long alias with arguments.
- There is nothing good about bash. You should stop using it, and your root shells should use ash or sash.
- csh and tcsh are below contempt. ksh is ok, because it's old school and powerful; unlike bash, its extensions to sh syntax aren't retarded, and they include important things like array manipulation and math, and for the most part the programming syntax is a subset of zsh's.
- autoremoveslash and autoparamslash (as in setopt...) are good. Quit being afraid. menucomplete is better than the alternative, although bad in huge directories. alwayslastprompt is slick and avoids pushing stuff off the screen. histignoredups makes scrolling through history less annoying. Any option that starts with "extended" should be turned on. Without rmstarsilent and clobber, the shell will make me very angry. listtypes lets you do most of what you do with "ls" without ever hitting enter.
- Read through all the man pages. You won't remember everything, but you'll remember generally what's available, and after a while you'll know where to look for what kind of information.