If you find yourself often typing some commands all the time, you can define an alias which is quicker to type but does the same thing. Search the manual pages of your shell for alias to find out more.
There are some things common to most of the shells which you really should know about. I'm going to assume that you already know about them; if not, make sure to read the manual pages for your shell until you do.
All standard shells offer at least two keymaps: one based on emacs-style bindings, and one based on vi-style bindings. bash and tcsh default to emacs-style, and zsh defaults according to whether you have $VISUAL or $EDITOR set to vi or emacs.
There are a number of core editing operations that you really should know in order to be able to work efficiently. (Given that emacs-style is more prevalent, I'll list the emacs-style bindings, but if you prefer vi-style, you should ensure you can perform these operations using that keymap instead. My personal opinion is that while vi can be extremely effective for text-editing full text files, the advantages that dual command/insert modality offers are less applicable when editing a single command line.)
Key combination | Effect |
Control-A | jump to start of line |
Control-E | jump to end of line |
Meta-B | move back one word |
Meta-F | move forward one word |
Control-D | delete character forwards/list completions/log out |
Control-K | delete to end of line |
Control-U | delete whole line |
Meta-Backspace | delete one word to the left |
Meta-D | delete one word to the right |
Control-T | transpose two characters |
Meta-T | transpose two words |
N.B. To do Meta- combinations on PC keyboards, try holding down Alt while pressing the other key. If your terminal emulator doesn't support this, instead try pressing (and releasing) ESCAPE before pressing the other key. I find the former more convenient, but the latter is more portable.
For simplicity, from now on I'll abbreviate Control-x as C-x and Meta-x as M-x.)
There are many more which make life easier, and you are strongly advised to read the manual pages to learn as many of them as possible.
An example of globbing is typing *.c to mean all files that end in .c, but actually globbing is much more powerful than this. (In fact, under zsh, it is so powerful, it almost makes find redundant.) Search the manual pages of your shell for `glob' to find out more.
Simply put, pipelines (denoted by the | symbol) allow you to take the output from one command and feed it to another, and redirection (denoted by symbols such as < and >) lets you direct output to a file. Search the manual pages of your shell for `pipeline' and `redirect' to find out more.
You can set one job going and put it in the background while you get on with other stuff. I'm going to assume that you know about this too; correct me if you don't. Search the manual pages of your shell for background and job to find out more.
If you find yourself often typing some commands all the time, you can define an alias which is quicker to type but does the same thing. Search the manual pages of your shell for alias to find out more.
Here are some features I consider absolutely essential for a really good interactive shell:
I'd say that the two most handy features of zsh and tcsh by a long way are the editor commands history-search-backward and dabbrev-expand, bound by default to the key sequences M-p and M-/ respectively. (See below for use within bash.)
If you type part of a command line and then press M-p, it will search backwards through the history for lines beginning with what you've typed so far. This means that you can very quickly and reliably fetch old lines out of the history. Say that you've just run LaTeX on a file called foo.latex:
tcsh$ latex foo.latex
Then you might run a few other commands (an xdvi maybe), make a few changes and then find that you want to rerun LaTeX on the file. All you need to type is la followed by M-p and the whole latex command magically pops up.
(Sceptics will note that this isn't such a good example because there are other, quicker ways of doing this anyway, e.g. using the emacs LaTeX mode).
M-/ is similar, except that it looks at the current word rather than the current line (a simplistic view of things is that command lines in the shell are built up from words separated with spaces). In other words, you can very quickly and reliably fetch old words out of the history. The power of this is amazing. For example, you might create a new directory:
tcsh$ mkdir /usr/local/src/my_project-with.an-awkward_name
and then maybe type a few other commands. Now you wish to copy all .c files from the current directory into the new directory. Type cp *.c /u and then hit M-/. The shell sees that the current word begins with /u, and looks back through the history for the first word beginning with this, which happens to be the horribly long and difficult-to-type directory name /usr/local/src/my_project-with.an-awkward_name you've just created. Up it pops, saving you much annoying typing. If there was another word in the history also beginning with /u since you created that directory, just keep pressing M-/ unless the right one appears.
I find that these two features alone save me oodles of hassle. bash can be configured to bind M-p and M-n to history-search-backward and history-search-forward respectively; put this in your .bashrc:
bind '"\ep":history-search-backward' bind '"\en":history-search-forward'
or if you really insist on using bash with vi mode (but see above):
bind -m vi-insert '"\ep":history-search-backward' bind -m vi-insert '"\en":history-search-forward'
Recent versions (bash 2 or later?) also have M-TAB bound to dynamic-complete-history, which is bash's equivalent of dabbrev-expand. For earlier versions, use:
bind '"\e\C-i":dynamic-complete-history'
(Note that in bash M-/ is already bound to complete-filename.)
zsh has M-p and M-n bound by default. There are two ways of getting it to perform dabbrev-expand-like behaviour. The first is the following trick (thanks to Bart Schaefer for this one):
bindkey '\ef' emacs-forward-word bindkey -s '^]/' '\eb!?\ef?:%\e!'
This is very simple to set up and should work with even older versions of zsh. However, it does not work well when completing more complex words, and is not configurable.
The best solution is to use a recent version of zsh. (Anything >= 4.0 should do.) These days, it has an unbelievably powerful new completion system (see below), and will provide the _history_complete_word function, which implements the widgets _history-complete-older (bound to M-/) and _history-complete-older (M-,). These are configurable; for instance I have in my .zshrc the following:
zstyle ':completion:*:history-words' stop yes zstyle ':completion:*:history-words' remove-all-dups yes zstyle ':completion:*:history-words' list false zstyle ':completion:*:history-words' menu yes
See the zshcompsys(1) man page for more information on these.
Another very sweet feature is incremental searching, usually bound to C-r (Control R). This is a sort of cross between the other two: press it, and start typing a word which exists somewhere in the history. By the time you've typed enough of it to uniquely identify it, you've plucked the whole of that line out of the history. This is available in bash (C-r by default), tcsh (not bound by default) and zsh (C-r by default).
There are many other cunning shortcuts; read the man pages to find more about them. I'll finish this section with a simple exercise for the reader: find out what M-. and/or M-, are bound to, and see if you can see why I use these many many times every day. If you can't, e-mail me for the answer, since again they are extremely handy!
insert-last-word ESC-_ ESC-.
Insert the last word from the previous history event at the cursor position. If a positive numeric argument is given, insert that word from the end of the previous history event. If the argument is zero or negative insert that word from the left (zero inserts the previous command word). Repeating this command replaces the word just inserted with the last word from the history event prior to the one just used; numeric arguments can be used in the same way to pick a word from that event.
From bash man:
yank-last-arg (M-., M-_)
Insert the last argument to the previous command (the last word of the previous history entry). With an argument, behave exactly like yank-nth-arg. Successive calls to yank-last-arg move back through the history list, inserting the last argument of each line in turn.
Completion is when you can press a key (often TAB) and the shell automatically cleverly completes the rest of the word you are typing, based on the context you are typing it in. Most shells only offer basic filename, hostname and command completion. Fully programmable context-sensitive completion is only available in tcsh and zsh by default, and in bash via a separate project. tcsh does it in a fairly messy and inflexible way. zsh has two systems: the older, obsolete one which uses a compctl builtin similar to tcsh's, and the new one which requires virtually no configuration, has out-of-the-box completion for tons of UNIX commands and is extremely sophisticated and powerful, but trivial to use as an end user. The bash programmable completion project is heavily based on this new system, but is much less featureful.
I used to be a fair fan of tcsh until I discovered zsh (bash 2 didn't exist in those days.)
I've edited and commented my .zshrc (main zsh interactive startup file) for your enjoyment. I strongly suggest that you read through it and edit it before use. Please note that there are other related files. http://www.adamspiers.org/computing/zsh/files/.zshrc http://www.adamspiers.org/computing/zsh/#other