Unix hints

This bit is for some handy unix stuff, geared towards matrix users. Please add any tips you think might be useful below. The crucial unix skill is being able to use the man and info programs, which give on-line help - but you can't use them until you know what command you want help with. That's what pages like this are for.

The unix learning curve is initially a lot steeper than that of a GUI based OS. But it's worth the effort. The interface is geared towards efficiency rather than friendliness, and when you get comfortable with it you can do far more than with any GUI. People used to DevStudio sometimes complain of a lack of IDE for Unix, to which the stock answer is the whole system is the IDE; combining the basic commands gives you file manipulation superpowers. You could read this article for more in this vein.

Basic shell stuff

A shell program is what sits between you and the computer after you've logged in; it interprets the commands you type, and is called the command line interface (CLI). On windows systems, you get command.com or cmd.exe as a rudimentary shell by default. Unix shell programs are a lot more sophisticated; you can do much more, much more quickly when you get used to them. The best unix shell programs are bash, tcsh, and zsh; tcsh is the default on matrix accounts, but all three are available (type bash to try bash, type zsh to try zsh). I'll just put a few tcsh basics here; some of these also work for bash.

Esc-p means press escape, let it go, then press p. An important shell concept is the history, a list the last number of commands you've typed. You can see your history with less ~/.history.

When the backspace and delete keys aren't working, sometimes Ctrl-H (^H) will do the job.

Scroll through previous commands with the up and down arrow keys.
Jump to the start of the current command line with ctrl-a.
Jump back and forward a word with esc-b and esc-f.
Delete from the cursor to the end of the word with esc-d.
Delete back one word with esc-backspace.
Delete from the current cursor position to the end of the line with ctrl-k.
Use esc-p to search back through the history. Example: suppose my last few commands have been:

vi websites.webm4
ls -l
vi unix.webm4
cat template

and I want to quickly recall that first vi command. I enter vi and press esc-p - and vi unix.webm4 appears. Pressing esc-p again searches back again, and vi websites.webm4 appears. Hurrah!

Use ! to recall the last command with a given prefix. So !v executes the last command that started with v, and !ls executes the last command that started with ls.

Filename completion is a handy feature of any decent shell. In tcsh, you can type the start of a filename and press ctrl-d to see possible expansions. When you have a unique prefix, you can press tab to complete the filename. Example: if on matrix I type z and press tab, nothing happens, because z is not a unique prefix. Pressing ctrl-d shows possible completions:

z         zdiff     zfgrep    zic       zmore     zsh-3.0.8
zcat      zdump     zforce    zipgrep   znew      zsh-3.1.9
zcmp      zegrep    zgrep     zipinfo   zsh       zsh.old

If I then add the letter g to make a unique prefix, pressing tab will complete the filename to zgrep.

Basic man

man is an abbreviation of manual; the man command offers basic on-line help for unix commands, important files, and programming interfaces. Issue

man ls
to see the help file for the ls command, for example.

The main thing with man is to know how to search, very necessary for the longer entries. You search by typing '/' and the string to search for. Pressing '/' and then enter repeats the last search. The -k switch is useful; the k signifies keyword. So if you want see all the exciting things you can do with files, you could execute man -k files. Also, remember you can do man man to read the manual page for man.

Basic vi

There are lots of tutorials already out there; I like this one. Find a few more here. It's worth knowing vi, though emacs is better.

More handy unix commands

grep(Find a pattern in text)

Grep is the archetypal obscure unix command, but it's simple really. Grep searches for stuff in text. A simple example of usage is

grep hdenman /var/apache/logs/error_log

which searches the current apache error log file for lines containing 'hdenman'. The error log file contains one line describing each failed webserver request (e.g. a 404 not found), and an error concerning this site will have 'hdenman' in it. So I can check that people aren't following broken links into the site with that command.

find(Find files satisfying some criteria)

The find command finds files; the syntax is not really

find [start-directory] [conditions] [actions]

but is easily explained that way; read the man page if you think you can handle the truth. [start-directory] is where to start looking; common choices are '.' (the current directory) and '/' (root, which starts a filesystem-wide search, which will take ages. See 'locate'). The [conditions] part specifies which files you're looking for; the handiest is name. For example, a condition of -name \*.html¹

Ordinarily, if you put an wildcard in a parameter, the shell expands it before handing the expanded version to the command. For example, an asterisk is replaced with the name of every file in the current directory before the find command sees it. This is not what's wanted, we want the find command to treat the asterisk as a wildcard (regexp?) rather than the shell. The backslash escapes the wildcard, causing the shell to pass it unexpanded to the command.

To see the shell expand wildcards before your very eyes, type ls * and press ^X* (control-X, then shift-8), assuming tcsh.

finds files ending in .html. The actions part is optional; if you leave it out, find just prints out the files it's found. An example of a useful action is exec, which executes a command on each file. So

find . -name \*.php -exec ls -l '{}' \;

executes ls -l on each file found.

locate(Search all files by name)

Locate is the way to find a file when you have no clue where it is. For example, if you want to find the apache log file (which, you happen to know, is called access_log), execute:

locate access_log

and you soon find it. Locate differs from find in that it generates a a snapshot of the entire filesystem once a day, which it can then search much more quickly than the filesystem itself. So if the file you're looking for was created since the last locate database update, locate can't find it.

perl(Does anything)

Perl one-liners are very useful; I use them mostly for making a change to a load of files (e.g. replacing one word with another). Here's an example:

perl -pi.bak -e 's/Jack/Jill/g' *.txt

That replaces 'Jack' with 'Jill' in all text files in the current directory, making backups of the original files with a .bak extension. Another one:

perl -pi -e 's#Colophon#Epilogue#ig' `find . -name \*.html`

This one replaces 'Colophon' with 'Epilogue', ignoring case, in all .html files in the current directory and subdirectories, without making any backups (see, the .bak after the 'i' is ommitted). Type man perlrun to see how the -p, -i, and -e options work, and man perlre to learn about regular expressions in perl.

You can use perl to emulate the watch command if your system doesn't have it. For example, to keep an eye on the size / date of the file Inbox, you can use:

perl -e '$|=1 
Setting $| to 1 forces stdout to be flushed after each write. If you fail to do this, you see nothing until you output a newline, stdout being in the normal way line-buffered.
; while (1) {chomp($_=`ls -l Inbox`); print "\r$_"; sleep(30);}' ¹
Setting $| to 1 forces stdout to be flushed after each write. If you fail to do this, you see nothing until you output a newline, stdout being in the normal way line-buffered.

Comments welcome...