Unix/Linux
o help
o recall
o find
o chmod
o groups
o replacing text in files
o mail
o tar
o grep
o less
o enscript
o disk space
o touch
o ftp
o cpu speed
o noclobber
o symbolic link
o cdpath
o getting an IP address
o window size & position
o ssh
o scp
o cron jobs
o at jobs
o make
o UNIX tricks
o tcsh tricks
Programs
o LaTeX tricks
o EMACS tricks
o IDL tricks
o firefox
o CVS
o da gimp
o powerpoint
Berkeley Only
o man or astro-man?
o scanning
o exabyte
o DLT
More notes
o linux desktop
o laptop
o miscellany

top | home
My accumulated computer knowledge. Cuz I forget. Thanks to Steve Dawson and his original set of shitty notes.

help
========
to get help on any UNIX command, simply type commandname -help
most of the time you just get the syntax of the command: more -help
sometimes you need two hyphens: less --help
sometimes you get absolutely no help: groups -help

if you want a seriously detailed description of a command:
man command_name

if you want to make a hardcopy of the man page:
man command_name | col -b > filename

if you want to find out where the man page is located:
man -l command_name


recalling a command
=======================
if you're using c shell:
if your history is set to a large enough value and you would like to 
repeat a command you've already typed in a while back, type:
!str  : runs the last command that started with str
!?str : runs the last command that containing str anywhere in line
!!    : repeat the last command

Type history to get your command history...
> history
   130  3:54    echo $path
   131  3:55    cd
   132  3:55    cd bin
Type !# to repeat the #th command...

> !131 

You can parse arguments from the previous line also:
!* : repeat all arguments
!^ : repeat the first argumnent
!$ : repeat the last argument

You can get really fancy with this.  The following become very useful
for aliases:

  Word Designators:
     A `:' (colon) separates the  event  specification  from  the
     word  designator.  It can be omitted if the word designator
     begins with a ^, $, *, - or %. If the word is to be selected
     from  the  previous  command,  the second ! character can be
     omitted from the event specification.   For  instance,  !!:1
     and  !:1  both  refer to the first word of the previous com-
     mand, while !!$ and !$ both refer to the last  word  in  the
     previous command. Word designators include:

     #         The entire command line typed so far.

     0         The first input word (command).

     n         The n'th argument.

     ^         The first argument, that is, 1.

     $         The last argument.

     %         The word matched by (the most recent) ?s search.

     x-y       A range of words; -y abbreviates 0-y.

     *         All the arguments, or a null value  if  there  is
               just one word in the event.

     x*        Abbreviates x-$.

     x-        Like x* but omitting word $.

  Modifiers:
     After the optional word designator, you can add  a  sequence
     of  one or more of the following modifiers, each preceded by
     a :.

     h         Remove a trailing pathname component, leaving  the
               head.

     r         Remove a trailing suffix of the form `.xxx', leav-
               ing the basename.

     e         Remove all but the suffix, leaving the extension.

     s/oldchars/replacements/ Substitute
               replacements for oldchars. oldchars  is  a  string
               that  may  contain  embedded blank spaces, whereas
               previous_word in the event designator
        ^oldchars^replacements^
        may not.

     t         Remove all leading  pathname  components,  leaving
               the tail.

     &         Repeat the previous substitution.

     g         Apply the change to  the  first  occurrence  of  a
               match  in  each  word, by prefixing the above (for
               example, g&).

     p         Print the new command but do not execute it.

     q         Quote the substituted words, escaping further sub-
               stitutions.

     x         Like q, but break into words at each space charac-
               ter, tab or newline.



better yet, type the first letter or two, then <esc>-<p> to
go forward in your history, type <esc>-<n>


find
========
find PATH -follow -name FILENAME -user USERNAME -size (+/-)SIZE
-follow causes symbolic links to be followed.
-name lets you look for a file with name FILENAME.
      True if pattern matches the current  file  name.
      Normal shell file name generation characters (man sh)
      may be used. A backslash (\) is used as  an escape  character  
      within the pattern.  The pattern should be escaped or quoted 
      when find  is  invoked from the shell. The character . at the
      start of a file name or immediately following a /,  as well
      as the character / itself, must be matched explicitly.
-user lets you look for files owned by USERNAME
-size lets you look for files less than (-), greater than (+), or 
      exactly SIZE kilobytes
-exec COMMAND '{}' \; allows you to execute COMMAND, '{}' is the current 
      path name COMMAND must end with \;
-ok   just like exec, but asks you if you want to execute.
-perm [-]onum  True if the  file  permission  flags  exactly
                match  the  octal number onum (see chmod(1)).
  If onum is prefixed by a minus sign (-), only
  the  bits  that  are set in onum are compared
  with  the  file  permission  flags,  and  the
  expression evaluates true if they match.
-type c        True if the type of the file is c, where c is
                b,  c,  d,  l,  p,  s, or f for block special
                file, character special file, directory, sym-
                bolic  link,  fifo  (named  pipe), socket, or
                plain file, respectively.
-user uname    True if the file belongs to the  user  uname.
                If  uname is numeric and does not appear as a
  login name in the  /etc/passwd  file,  it  is
  taken as a user ID.
-mtime (+/-)n  Modification times (less/more than) n day(s) ago.
-newer fname   Modification times newer than that of fname.
-prune         Do not examine any directories or files below this.

Recursively print all file names whose permission mode
exactly matches read, write, and execute access for user,
and read and execute access for group and other.
example: % find . -perm u=rwx,g=rx,o=rx

EXAMPLES: 

(0) here's one I need a lot: to get the absolute path to files, use
$PWD as the input directory: 
find $PWD

(1) find all files >2000k and lists them:
find . -type f -size +2000c | xargs du -k | less

(2) how many files in just this directory?
find . \! -name . -type d -prune | wc -l

(3) are any of my files writable by others...
find $HOME -type f -perm -og+w -ls

(4) where are all the .tex files hiding in my home directory?
(Follow symbolic links!):
find $HOME -follow -name \*.tex

(5) find all backup files starting with a,b, or c and ending in ~:
find $HOME \( -name \[a-c\]\*~ -o -name .\[a-c\]\*~ \)

(6) find all files readable by the group other but not 
readable by other users:
find . -type f -group other -perm -g=r \! -perm -o=r

(7) you have to surround {} in an exec command with spaces.  however,
this adds space that you may not want when echoing.  use "\b" after
the {} to add a backspace character:
find . -exec echo {} "\b:" \; -ls

(8) find all "dot" files and directories, but don't match the 
. and .. directories:

find . -type f | grep -E "/\.+[^/]+"$

-------------------------------

UNDERSTANDING HOW TO USE PRUNE:

start from home directory, find all files ending in .pro but skip ALL directories named idl:
find ~ \( -name \*.pro -o \( -name idl -prune \) \) -type f
does file end with .pro?
yes
   is it a file?
   yes print
   no skip
no
  is the name idl?
  yes don't go into this directory
  no is it a file?
        yes print
 no skip

avoid searching backup directory...
find $cwd \( -type f -exec lookin {} '/home/robishaw' \; -o \( -name bak -prune \) \)

-------------------------------

when using find to look for files with certain time stamps, find may
not be fancy enough since it only deals in units of days.  What if you
wanted to know which files were created since 2:34 this afternoon?

Make a temporary file with that time stamp using touch:
touch `date '+%m%d'`1434 /tmp/timestamp
find . -newer /tmp/timestamp
\rm -f /tmp/timestamp

-------------------------------

find all the directories JUST in THIS directory:
find . -type d \! -name . -prune

to find just the files in the current directory:
find . \! -name . \( \( -type d -prune \) -o -print \)

-------------------------------

if you want to cut the "./" out of each listing:
find . | cut -c3-

-------------------------------

to use find to get the full qualified path to a specific path:

> find ${cwd} -prune

-------------------------------

a wicked quick way to search through useful files is to (a) pipe the find
output into xargs and (b) avoid looking in non-text files.

First, define an alias to make life easier:

> find . -type f -print0 | \
grep -zivE "\.(au|wav|ram|mp3|avi|mpg|mpeg|flc|sav|dvi|eps|ps|pdf|jpg|jpeg|gif|tif|png|zip|gz|Z|bz2|tar|jar|fit|fits|tfm|so|db|pf|o)"$ | \
xargs -0 grep -in search_string

What's all this?  Here's what this is doing:

       v find only files
find . -type f -print0
               ^ print out the file names separated by the null character

grep -zivE "\.(au|wav| ... )"$
the search string is a regular expression that will match all files that
end (that's what the $ does: matches end of line) with the suffixes listed;
the suffixes should be separated by the "|" character and the entire set
should be enclosed in parentheses.
the flags mean:
    -z: incoming data is separated by null character, not newline
    -i: do a case insensitive search (match .mp3 or .MP3)
    -v: invert the match: return files that DON'T end in these suffixes
    -E: search pattern is an extended regular expression

      v input items terminated by null character, not whitespace
xargs -0 grep -in s5Bearch_string
               ^ case insensitive search and print line number of match

-----------------------------------

I have a perl script called fixfile that replaces string_old with
string_new in a file, so if I change my directory hierarchy I can easily
fix up any hardwired paths by running the above search with slight
modifications:

> find . -follow -name mail -prune -o -type f -print0 | xargs -0 grep -Zl string_old | xargs -0 fixfile string_old string_new

Here we had a bunch of weirdo HTML tags in files like so \<b\>; I
went and changed them back to <b> like so:

find . -type f -name \*html -print0 | xargs -0 grep -Zl "\\<b\\>" | xargs -0 fixfile "\\\<b\\\>" "<b>"

And then went and changed every <b> to <strong> like so:

find . -type f -name \*html -print0 | xargs -0 grep -Zl "<b>" | xargs -0 fixfile "\<b\>" "<strong>"

This assumes that there aren't more than something like 12000 files that
need to be fixed... because I can't figure out how to pipe the xargs -0
grep -l string_old output into a null-character-separated list (just using
grep -zl doesn't work).  So we just pass a newline-separated list of files
to fixfile.

Similarly, the user might want to pipe the output of find to "file" rather
than grepping for the extension.  Unfortunately, the output of file will
end up with newline characters as in the example above.  So you could do
the following assuming there won't be many matches (but this is a very poos
assumption in this case because most files WILL BE text files!):

> find . -type f -print0 | xargs -0 file | grep -i text | cut -f1 -d: | \
xargs grep -in search_string

In addition, there are a ton of file types that do not have text in the
returned output from "file", so I prefer the method of explicitly avoiding
certain extensions.


chmod
=========
used to change the permissions of a file or directory. it's typical to
add permissions using an octal integer format where the integers are:

0 No read/write/executable
1 executable
2 writable
3 writable/executable (=2+1)
4 readable
5 readable/executable  (=4+1)
6 readable/writable   (=4+2)
7 readable/writable/executable (=4+2+1)

so, 

   > chmod 755 filename

makes filename readable and executable by group and other. However,
the man page suggests that you avoid using the "obsolescent" octal
integer format.  Instead you can use the letters u(ser), g(roup),
o(ther), r(ead), w(rite), or x(-ecutable) with a "+" to add a
permission or a "-" to take away a permission. i.e. to add executable
permission for group and other:

   > chmod go+x filename

If you want to a permission change to recursively descend through a
directory, use the -R flag (in front of the permission code!):

   > chmod -R o-rx directoryname

To define a umask, the value of each specified digit is subtracted
from the corresponding "digit" specified by the system for the
creation of a file, i.e., umask 022 removes write permission for group
and other (files normally created with mode 777 become mode 755; files
created with mode 666 become mode 644).  Best to just keep it 022!


groups
==========
to see what groups exist and who belongs to them:

On systems using NIS+:

   > niscat group.org_dir

On systems using NIS:

   > ypcat group

You can check to see which groups you belong to with:

   > groups

Sometimes you want certain other people to be able to write to files in
your directory (like when you use CVS to control papers or programs with a
group).  The default group you belong to might be "bin" or "user" on linux
or "other" on solaris.  However, you cannot create a group, so send an
email to the sysadmin and ask them to create a group with the users in your
group.

Now that you have a group set up, you can change the group ID of a
file with:

   > chgrp groupname filename

If you want to change the group ID for all files below a certain
directory, use the -R (recursive) flag:

   > chgrp -R groupname directoryname

If you want all the files created in a directory to be created with
the group ID of that directory, you need to set the "sticky bit" for
group permission:

   > chmod g+s directoryname



replacing text in files
===========================

to change all the occurrences of word1 to word2:

sed s/word1/word2/g <infile> <outfile>
mv outfile infile

This is the simplest case.  For complicated cases, learn PERL.


mail
========
ls > file        : outputs contents of ls to file
mail bla@bla < file     : mails file to bla@bla
all mail distribution lists at berkeley are stored in /adm/users


tar
========
If you want to make a tape archive, use tar.  This is a fancy
way of saying: if you wanna take a bunch of files and directories and
pack them all up in one handy file that you can unpack later, then use

tar.  You should do this if you are transferring multiple files
over the internet or even to another file system.  Here is the syntax
(the v option tells tar to be verbose, the z option tells tar to gzip the
archive when making it, or ungzip it if reading it):

tar zcvf fname.tar.gz file1 file2 file3 file4  => c = create 
tar zxvf fname.tar.gz    (untar)               => x = x-tract (untar)
tar ztvf fname.tar.gz    (JUST list files)     => t = table of contents

In olden times, the z option didn't exist, so you used to have to pipe the tar
through a gzip.  For completeness, here was how you would do that...
> tar cvf - file1 file2 file3 | gzip -c > file.tar.gz
To unpack a tarred and gzipped file:
> gunzip -c file.tar.gz | tar xvf -

If you have symbolic links in your directory tree, then the default
behavior of tar is to avoid following symbolic links.  So if you want
them followed, include the the h flag.
> tar cvhf tree.tar directory

If you want to exclude all directories named /sav then tar has a
convenient method for doing this:
> tar zcvf tree.tar.gz --exclude=sav directory

You can also exclude files and directories by listing them in a file.  You 
have to make sure that the relative paths are the same for this to work.

> tar cvhXf exclude_file tree.tar directory

The order is important! I listed the flags in the order Xf, so the
exclude file must come before the output file.  I could have
flipped them if I wanted to:
> tar cvhfX tree.tar exclude_file directory
Just make sure you keep the order of the file names the same as the
flags!

Finally, if you want to delete the files you've just archived, you can include
the --remove-files keyword.


grep, egrep, fgrep
======================
Say, man, what's the difference between grep, egrep, & fgrep?

Well, grep searches a file for a text pattern. fgrep

searches for a fixed-character string; no regular expressions are
used. egrep uses full regular expression matching.

flags for grep, egrep, & fgrep:
-i : ignore case of strings being matched
-c : only print count of lines that contain the pattern
-s : suppress display of any error messages for nonexistant/unreadable files
-n : precedes matched line with file line number
-h : suppress printing filenames when searching multiple files
-l : print names of files with matching lines without repeating file name
-v : displays all lines not matching a pattern

> grep -i setenv ~/.login | egrep -v "TEX|MAN"


using less
==============
less is like more, only better because you can go backwards, it
doesn't have to read in the whole file at once (which sucks when
more-ing big files), you can search for words and do a whole bunch of
cool things.  but, if you need to use anything beyond the
following, may as well just use emacs:

h       : display help

(Below, type N (a number) before the command where applicable.)

<RETURN>: scroll forward 1 line (or N lines)
e       : scroll forward 1 line (or N lines)
j       : scroll forward 1 line (or N lines)

y       : scroll back 1 line (or N lines)
k       : scroll back 1 line (or N lines)

<SPACE> : scroll down one full screen (or N lines)
f       : scroll down one full screen (or N lines)
b       : scroll back a full screen (or N lines)

d       : scroll forward 1/2 screen
u       : scroll backward 1/2 screen

g (or p): go to top of file
G       : go to end of file
Ng      : go to line N

/pattern: search forward for pattern
?pattern: search backward for pattern

n       : repeat previous search
N       : repeat previous search in reverse direction

q       : exit

For more less help, man page.


enscript
============
> enscript -r -B -j -fCourier8 -pfile.ps file

useful options:
-B   : omits the page header
-r   : rotates to landscape
-j  : print borders around columns
-2   : prints 2 columns per page.
--columns=NUM  : prints NUM columns per page.
--word-wrap : wraps long lines.


disk space
==============
Disk Usage
--------------
du -ks ~ tells you the # of kb being used in home directory
du -k .  tells you the # of kb being used in current directory and lists
         all files and directories as well
  Linux: -H prints the sizes in human-readable format and uses powers of 1000
            (use -h to read powers of 1024)
  -c print a grand total (e.g., du -Hc papers code data)
Solaris: -o   Do not add  child  directories'  usage  to  a  parent's
              total.   Without  this  option,  the usage listed for a
       particular directory is the space taken by the files in
       that directory, as well as the files in all directories
       beneath it.  This option does nothing if -s is used.

Disk Usage for Filesystem
-----------------------------
df -k .  tells you useful information about the disk you're on now (like % 
         of disk being used!)
df -k    tells you useful info about all file systems that have been mounted
  Linux: -H prints the sizes in human-readable format and uses powers of 1000
            (use -h to read powers of 1024)
Solaris: -b prints the free space

To just get the size of each directory file and directory in a directory:

du -hc --max-depth=1


touch
=========
changes the time stamp on a file
use the -r option to set a timestamp to match that of another file
> touch -r copy_my_timestamp new_file


ftp
=======
> ftp -i hostname

The -i flag shuts off interactive prompting when transfering multiple
files, cuz that's annoying.

Here are the quickie commands to get around once you're there:
dir   : like ls -l
ls    : like plain ole ls [-al options]
pwd   : current working directory
get   : retrieve one file
put   : stick local file on remote machine
mkdir : make a directory on remote machine
rmdir : kill directory on remote machine
rename: rename file on remote machine
mdir  : like dir, but takes multiple files/directories
mls   : same dealio
mget  : retrieve multiple files from remote machine
mput  : stick local files on remote machine
prompt: toggle interactive prompting
help  : get help on command name
close : exit remote machine
quit  : exit ftp connection


to get CPU speed
====================
Which version of UNIX are you running: uname -a

  Linux: cat /proc/{cpuinfo,meminfo}
Solaris: fpversion  (also psrinfo -v)
         Display system configuration with: sysdef


noclobber
=============
add "set noclobber" to .cshrc if you don't want to overwrite
redirected computer output.  "unset noclobber" and add "set clobber"
when you get sick of this.

Or, if you want to remain cautious, yet really want to
overwrite something, use >!, e.g.:

   > more ~/.cshrc >! tmp


symbolic link
=================
ln -s /this/is/the/directory/that/will/be/linked/from/here directoryname 


cdpath
==========
if you work in an environment where your stuff is spread over many disks, you
might really like to know about the system variable $cdpath.  stick all the root
directories that you frequently work in into this variable.  so stick something
like this in your .cshrc file:

set cdpath=(/home/bobo /home/robishaw /home/anything)

now you can cd into these from any place.  Say you have a directory named
/home/robishaw/papers and you're currently in /j/bongo... then all you'd need to
type is cd papers and it will be able to find it in /home/robishaw since that's
in your $cdpath.


obtaining an IP address
===========================

On Linux use host...
> host astro.berkeley.edu
astro.berkeley.edu has address 128.32.92.108

On Solaris use nslookup...
> nslookup astro.berkeley.edu
Name:    astro.berkeley.edu
Address:  128.32.92.108

You can get also get the DNS domain name through a little trickery.

On Solaris:
> /usr/bin/awk '/domain/{print $2}' < /etc/resolv.conf
Berkeley.EDU

You can convert to lower case like so:
> /usr/bin/awk '/domain/{print $2}' < /etc/resolv.conf | tr '[:upper:]' '[:lower:]'

On Linux:
> host $HOST | cut -d. -f2- | cut -d\  -f1
berkeley.edu


getting window position and size
====================================
use xwininfo to get the size, position and other attributes for a window

    > xwininfo

    xwininfo: Please select the window about which you
              would like information by clicking the
              mouse in that window.

if you want the info for the entire display, just type:

    > xwininfo -root


using ssh
=============
used to establish a secure connection with a remote machine.

You need to be aware that there are many versions of ssh in the world.
This might make life difficult for you if two computers with different
versions try to talk with one another.  You can find the version with
the -V flag:

On some remote system:

    > ssh -V
    OpenSSH_3.4p1, SSH protocols 1.5/2.0, OpenSSL 0x00907003

Here at Berkeley:

    > ssh -V
    ssh: SSH Secure Shell 3.1.0 (non-commercial version) on sparc-sun-solaris2.7

This is the simplest syntax of the ssh command line:

    > ssh [-l login_name] hostname [command]

or

    > ssh login_name@hostname [command]

If you work between many remote systems, you'll get sick of being
prompted for your password very quickly.  There is a solution to this
problem.  However, it is very confusing business due to the different
versions of ssh floating around the world.  The current version of ssh
here in Berkeley (which is actually ssh2!) will create a .ssh2
directory in your $HOME directory.  OpenSSH (at other sites) will
create a .ssh directory in your $HOME directory.


So, first let's worry about dealing with your Berkeley account.

In order to avoid having to enter your password every time you log into a
machine, you have to share your "public key" with other computers.

(1) First, type:

    LOCAL> ssh-keygen2

  you get something like this:

  aster:/hvc/robishaw/.ssh2> ssh-keygen2
  Generating 1024-bit dsa key pair
     5 .oOo.oOo.oOo
  Key generated.
  1024-bit dsa, robishaw@aster, Fri Oct 26 2001 03:28:04
  Passphrase : 
  Again      : 
  Private key saved to /hvc/robishaw/.ssh2/id_dsa_1024_a
  Public key saved to /hvc/robishaw/.ssh2/id_dsa_1024_a.pub

  N.B. Your passphrase should be >= 20 characters.
       This creates a $HOME/.ssh2 directory.
       NEVER give your Private key to anyone else!
       You can pass the Public key to other computers.

(2) Now create an identification file in $HOME/.ssh2:

    LOCAL> echo "IdKey id_dsa_1024_a" > $HOME/.ssh2/identification

(3) Copy your public key (id_dsa_1024_a.pub) to the ~/.ssh2 directory
    on a REMOTE machine:

    LOCAL> scp id_dsa_1024_a.pub you@remote.edu:/userhome/.ssh2/hostkeys/key_yourmachine.edu.pub

(4) If an authorization file does not exist on REMOTE, then:

    REMOTE> echo "Key hostkeys/key_yourmachine.edu.pub" > authorization 

    else, if it already exists:

    REMOTE> echo "Key hostkeys/key_yourmachine.edu.pub" >> authorization 

(5) Repeat steps 0-4 from REMOTE.


OK.  Now suppose your REMOTE account is not running ssh2, but OpenSSH_3.4p1.





* Use -f flag if you want to run a program from another host in the
  background. Example:

    aster> ssh -f robishaw@deep.berkeley.edu emacs /hvc/robishaw/.cshrc



using scp
=============
to securely copy files from one machine to another. 

scp [[user@]host1:]/pathto/filename1 [[user@]host2:]/pathto/filename2

You MUST use the ABSOLUTE PATH to the REMOTE machine location.

You will be prompted for a password (unless you followed the
instructions above). File specifications like '*' must be surrounded
by quotes or protected by a \ !

Use -r flag to recursively copy entire directories! For big directory
structures, probably wicked fastah to tar the relevant directories
and scp.

Use -p flag to preserve file attributes and timestamps.


Examples for clarity:

To copy FROM LOCAL host TO REMOTE host:

       > scp path/to/localfile name@remotehost:/absolute/path/to/remotefile 
       > scp -r path/to/localdir name@remotehost:/absolute/path/to/remotedir 

To copy FROM REMOTE host TO LOCAL host:

       > scp name@remotehost:/absolute/path/to/remotefile path/to/localfile
       > scp -r name@remotehost:/absolute/path/to/remotedir path/to/localdir

To avoid recursively copying deep structure, but you want to copy the
contents of an entire directory:

       > scp name@remotehost:/absolute/path/to/remotedir/\* path/to/localdir



cron jobs
=============
We use crontab, which may or may not do exactly what you tell it to do at
a specified time.  But for the most part folks in the know are happy
with the results.

Make a file to combat your senility.  We stick the following in the file:

        0 7 24 * * echo "PAY RENT" | mail robishaw

The numbers represent the following:

        Minute  0-59
 Hour    0-23
 Day     1-31
 Month   1-12
 Weekday 0-6  (0 = Sun)

You can get fancy by using commas between multiple values, a hyphen for 
a range, and an asterisk for all values. There is a way to use
Unix Power Tools script whichweek.sh to be slick about selecting which day
you want the task completed. Make sure this file is executable!!!

After the file is made we need to tell our computer to remember to do
this task:
            > crontab <filename>

One can only use one crontab file per machine.  To see who's got crontabs
running on a machine, log in and type:
            > ls /usr/spool/cron/crontabs

Or to just see if you've got one running:
            > ls /usr/spool/cron/crontabs | grep $USER

To edit the current crontab:
            > crontab -e

To print the result of your crontab just type:
            > crontab -l

To get rid of your crontab:
            > crontab -r



at jobs
===========
at is like crontab, only you enter the commands you want executed at
the standard input and they are grouped together and executed at the
specified time.

OPTIONS:
-c : C shell used to execute the job
-k : Korn shell used
-s : Bourne shell used
-l : lists all jobs scheduled for the invoking user
-m : sends mail to invoking user after job runs
-f file : specifies the path of a file to be used as the source of
          the at job instead of standard input
-r jobid: removes job with jobid
-t time : Submits the job to be run at the time specified by
          the time option-argument, which must have the format 
   as specified by the touch(1) utility.


make
========
make is fun.  N.B. (on Solaris machines, use gmake)
You can define "macros" using "=":
    FILE = paper
    DVIPSIT = dvips -o

A macro is invoked by using the form $(macro_name) or ${macro_name}.

Need to use "\" to continue long macros and rules.

There are certain special macros predefined.

    1. $@ is the name of the file to be made. 
    2. $? is the names of the changed dependents. 
    3. $< the name of the related file that caused the action. 
    4. $* the prefix shared by target and dependent files. 

The general syntax of a Makefile Target Rule is 

    target [target...] : [dependent ....]
           [ command ...]

Items in brackets are optional, ellipsis means one or more. Note the
tab to preface each command is required.

When you say "make target" make finds the target rule that applies
and, if any of the dependents are newer than the target, make executes
the commands one at a time (after macro substitution). If any
dependents have to be made, that happens first (so you have a
recursion).

A make will terminate if any command returns a failure sta-
tus. That's why you see rules like:

clean:
         -rm *.o *~ core paper

Make ignores the returned status on command lines that begin with a
dash, e.g. who cares if there is no core file?

Make will echo the commands after macro substition to show you what's
happening. Sometimes you might want to turn that off by preceding the
command with @, i.e. @echo The Yankees suck.

People have come to expect certain targets in Makefiles. You should
always browse first, but it's reasonable to expect that the targets
all (or just make), install, and clean will be found.

     1.make all -- should compile everything so that you can do local
     testing before installing things.

     2.make install -- should install things in the right places. But
     watch out that things are installed in the right place for your system.
 
     3.make clean -- should clean things up. Get rid of the executables,
     any temporary files, object files, etc.



UNIX tricks
===============

PATH environment variable
=============================

Environment variables that list directory paths are colon-separated and
hard to read.  I came up with an alias that helps parse the list and make
it easier to read:

alias listpath  'echo ${\!:1} | \awk -F":" '\
		''\''{for (i=1;i<=NF;i++) {print $i}}'\'''

I haven't been able to find anything definitive about what order the
directories in $PATH should be in.  I think the best you can do is assume
that the system administrator defined the order of the path in a smart way.
So before altering the path in your shell initiation file, you should
consider keeping the default order unchanged, unless you have a good reason
not to.

Here are the default paths for a number of accounts I have:

berkeley linux:
/opt/kde3/bin:/opt/gnome/bin:/usr/games:${HOME}/bin:/usr/bin/X11:/usr/bin:/bin:/usr/local/bin

berkeley unix:
/bin:/usr/bin:/usr/ucb:/usr/bin/X11:/usr/local/bin:/usr/local/bin

laptop:
/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games

green bank:
/usr/kerberos/bin:/bin:/sbin:/usr/bin:/usr/sbin:/opt/local/bin:/usr/local/bin:/usr/X11R6/bin:${HOME}/bin:.

arecibo linux:
/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin

arecibo unix:
/usr/bin:/bin:/usr/sbin:/sbin:/pkg/sec/bin

You can see these sysadmins are not of the same mind when it comes to path
order!  So I've decided to take some steps to ensure sanity when working on
different systems.  First of all, I keep a ~/software directory in which I
configure and make local software if the sysadmin is slacking in keeping
vital software up-to-date.  So, obviously, I want these directories at the
front of my $PATH so that my software will be called before the local
system version.  I also have a ~/bin directory where I store useful scripts
that I've written.  I'd like this up front too in case there's something on
a system that happens to have the name of one of these scripts.

One conundrum is that it is a security risk to have /usr/local/bin before
/bin since someone could stick a nasty program named after any of the
standard system utilities that live in /bin, like ls, in /usr/local/bin.
However, if you worry about this, then having local executables in
/usr/local/bin is kind of useless since the versions in /bin will be the
defaults.  Another security risk is having . (the current directory) in the
front of your path; same reason as above.  Most people I know live with the
risk.

One set of tools to help manage your path is the following csh aliases
which allow the user to prepend or append a pathname to $PATH.  These are
floating around on the internet and are incredibly scary looking.  With a
lot of hard-earned knowledge I will break them down:

alias append_path 'if ( $\!:1 !~ \!:2\:* && $\!:1 !~ *\:\!:2\:* && $\!:1 !~ *\:\!:2 && $\!:1 !~ \!:2 ) setenv \!:1 ${\!:1}\:\!:2'
alias prepend_path 'if ( $\!:1 !~ \!:2\:* && $\!:1 !~ *\:\!:2\:* && $\!:1 !~ *\:\!:2 && $\!:1 !~ \!:2 ) setenv \!:1 \!:2\:${\!:1}; if ( $\!:1 !~ \!:2\:* ) setenv \!:1 \!:2`echo \:${\!:1} | /usr/bin/sed -e s%^\!:2\:%% -e s%:\!:2\:%:%g -e s%:\!:2\$%%`'

They are called like so:

prepend_path PATH /usr/local/bin
append_path PATH /usr/sbin

Notice, you DO NOT pass the entire environment variable $PATH to these
aliases, only the name PATH; also, you can use these for ANY
colon-separated list of paths, like MANPATH or LD_LIBRARY_PATH.

Now, what on earth do those things actually do?  The short description of
append_path is simple: if the directory you're trying to add is not
anywhere in the current path then just add it to the end of the path.

Why is prepend_path so much longer?  Because it's trying to do something
much more tricky (and doesn't completely succeed!) It says: if the
directory you're trying to add is not anywhere in the current path then
just stick at the front of the path, BUT if it is somewhere in the path
already, then unless it's already at the front of the path, remove any and
all references to this directory from the path and then stick this
directory at the front of the path.

Now, we'll take a look at each step and we'll find that prepend_path is not
successful at it's task since it is written incorrectly.  It's not hard to
see why the incorrect version is all over the internet!  Nobody is going to
take the time to figure out how the hell it works!

Let's break this down so that it makes the slightest damn lick of sense...
First off, the $ is there to tell us to look at an environment variable.
The arguments to the alias are denoted by !:1 !:2 etc.  You need to protect
the exclamation point so that the shell doesn't go and grab the history
which is also accessed via the exclamation point.

Let's look at prepend_path since it's the hardest to understand. Let's just
assume !:1 is equivalent to PATH, to make explanation easier...

	(1) if ( $\!:1 !~ \!:2\:*
	First check to see if $PATH is NOT equal to the second argument
	with :* appended to it.  I.e, is the 2nd arg NOT the first
	component of $PATH?

	(2) && $\!:1 !~ *\:\!:2\:*
	If the last part was TRUE, then check to see if $PATH is NOT equal
	to the 2nd arg with *: prepended to it and :* appended to it. I.e,
	is the 2nd arg nowhere to be found in the middle of $PATH?

	(3) && $\!:1 !~ *\:\!:2
	If everything has been TRUE so far, check to see if $PATH is NOT
	equal to the 2nd arg with *: prepended to it. I.e, is the 2nd arg
	NOT the last component of the $PATH?

	(4) && $\!:1 !~ \!:2 )
	Finally, check to see if $PATH is NOT just plain equal to the 2nd
	argument.

	(5) setenv \!:1 \!:2\:${\!:1};
	If none of the above were TRUE, meaning if the second argument
	appears absolutely nowhere in $PATH, then set the environment
	variable PATH to the original value prepended by the 2nd arg
	followed by a colon.  The semicolon means we're not done yet.

	(6) if ( $\!:1 !~ \!:2\:* )
	Now let's check to see if $PATH is NOT equal to the 2nd arg
	with :* appended to it. I.e, let's stop here if the 2nd arg is
	the first component of $PATH. [N.B. I fix this below since this
	prevents our ability to remove duplicate appearances of the path
	we're trying to add if that path happens to have one of the
	duplications as the first component of $PATH... more details
	below.]

	(7) setenv \!:1 \!:2`echo \:${\!:1} | /usr/bin/sed -e s%^\!:2\:%% -e s%:\!:2\:%:%g -e s%:\!:2\$%%`
	If this is TRUE then, set the environment variable PATH to the 2nd
	arg followed by a complex string.  This string can be read as
	follows: echo a colon (\:) followed by the contents of the PATH
	environment variable (${\!:1}) and send this result through the
	following complicated machinery...

		(a) sed -e s%^\!:2\:%%
		First, if the expression begins with the 2nd arg followed
		by a colon, then cut it out the expression [N.B. This is
		a wasted statement since a colon has been prepended to
		the string sent in: you can never have this scenario!
		Obviously, we will fix this below.]

		(b) -e s%:\!:2\:%:%g
		Next, replace the 2nd arg preceded by a colon with just a 
		colon, and do this everywhere it's found.

		(c) -e s%:\!:2\$%%
		Finally, if the 2nd arg is found at the end of the PATH, 
		remove it as well as the colon preceding it.

	If there are multiple entries of the 2nd arg already in $PATH, only
	the 2nd and 3rd sed operations will remove the multiple cases. If
	there are duplicates and one of them happens to be the first in the
	path, the duplicates are NOT removed. Also, this assumes sed is
	recursive, but it is not, so if your path is set to b:a:a:a:a:b
	then step (b) above will replace only the values sandwiched by
	colons: 
	b:a:a:a:a:b => b:a:a:b    similarly:    b:a:a:a:a:a:b => b:a:a:b
	 ^^^ ^^^                                 ^^^ ^^^ ^^^
	So we will use a fancy feature of sed (which the sed manual claims
	are "for die-hard SED programmers"!) which allows us to define a
	label which we can branch to.  In this way, we can keep passing
	through stipping out :a: until there are no more matches.

Here is how we will fix the sed operation:

echo :${\!:1} | /usr/bin/sed -e s%^:\$%% -e :a -e s%:\!:2\:%:%g -e ta -e s%:\!:2\$%%

What did we do?  We still pass in a prepended colon into the sed
machinery. We handle the extremely peculiar case of having an empty PATH
passed to us (-e s%^:\$%% strips out the lone colon that would be
unnecessary); then we set a label named a to which we might return to (-e
:a); then we remove all cases of the directory sandwiched on both sides by
a colon (-e s%:\!:2\:%:%g - the g makes sed remove all cases); next, if
there were any successful substitutions, we go back to the label a and do
the substitution again (-e ta); finally we get rid of the directory if it
is at the end of the path (s%:\!:2\$%% - the dollar sign is the end-of-line
character for regular expressions.) Also we removed the if statement from
the second step altogether since it prevents us from removing duplicate
path elements if one of them happens to be the first component of $PATH.

To handle the weird case of having an empty PATH passed to us (you would
define an empty path like so "setenv PATH"), we need to add one more
condition to the first part of the alias: simply avoid executing the first
setenv if the first argument is an empty string (\!:1 !~ ""). Then in the
second part, we check to see if the input string is a single colon and get
rid of it if so: sed -e s%^:\$%%.  We also add a second statement to
append_path to cover this case; it's pretty easy: if the path was blank
just set the path equal to the directory.

FINALLY, THE CORRECT ALIASES ARE:

alias prepend_path 'if ( $\!:1 !~ \!:2\:* && $\!:1 !~ *\:\!:2\:* && $\!:1 !~ *\:\!:2 && $\!:1 !~ \!:2 && $\!:1 !~ "") setenv \!:1 \!:2\:${\!:1}; setenv \!:1 \!:2`echo :${\!:1} | \sed -e s%^:\$%% -e :a -e s%:\!:2\:%:%g -e ta -e s%:\!:2\$%%`'

alias append_path ' if ( $\!:1 =~ "" ) setenv \!:1 \!:2; if ( $\!:1 !~ \!:2\:* && $\!:1 !~ *\:\!:2\:* && $\!:1 !~ *\:\!:2 && $\!:1 !~ \!:2 ) setenv \!:1 ${\!:1}\:\!:2'

Now, the reason that append_path does NOT strip out any existing mention of the
path and move it to the end is that a program or sysadmin probably put a
directory in its path position for a good reason, so moving it to the end
of the path is probably not a good idea.  You could easily come up with a
sed operation to mimic prepend_path but I've decided that if I really need
to do so, I would use an alias called rmpath to strip out ALL occurrences
of the directory from the path and then run append_path.  The definition of
rmpath is:

alias rmpath    'setenv \!:1 `echo ${\!:1} | \sed -e :a -e s%:\!:2\:%:%g'\
		'-e ta -e s%^\!:2\:%% -e s%:\!:2\$%% -e s%^\!:2\$%%`'


tcsh tricks
===============
you can set the default printer either of two ways:
* set the $PRINTER environment variable
* store this in a file in your home directory named .printers:
_default printer_name

bindkey tells you the key bindings.
^  : CTRL
^[ : ESC
^? : BACKSPACE

you can set the key bindings in the shell to the emacs key bindings by
putting this in your .cshrc file:
bindkey -e

check this out: tcsh will actually execute a specific command every
few minutes if you want it to!  This is way cool.  Say you have an
email signature randomizer and you want to run it every ten minutes:

set tperiod 10
alias periodic 'email_ranomizer_name'

If you want a less periodic interval, then alias this to beepcmd:

alias beepcmd 'email_randomizer_name'

This will be executed every time the shell attempts to beep the terminal.

completions
==============

Completions are pretty damn cool. They help the forgetful man. The big idea is
that you can tab complete to get all sorts of information about what should come
next in the command call.  For instance, say you forget all the flags that a
command takes, type command -<TAB> and, if you've written the completion
correctly you can output all the possible options.  Damn, that's cool.  Even
cooler is, say the command only takes arguments that are files or directories or
user names or environment variables... well, you can have your tab completion
search for only the appropriate type of argument.  Shazaam.

Here's a quick tutorial on how these are set up.  I learn this junk and forget
it when I look at the completion syntax a year later.  So here goes.  The syntax
for a completion is as follows:

complete command word/pattern/list/suffix

(When dealing with directory names which have forward slashes, you can use
another reserved character to separate the parts of the completion, which
you can do in sed as well, so try @ or %)

word and pattern tell us how to choose which words to be completed.  list tells
the user the word list from which to choose the possible completions. suffix can
specify a suffix other than default space or slash that will be placed at the
end of the completion.

word can be one of five letters:
p - position: a given word in a position
c - the current word: pattern is matched to beginning of current word
n - the next word: pattern is matched to beginning of previous word
C - like c, but includes patten when completing current word
N - like n, but matches word two before the current word

pattern is different depending on what word was and can contain operators
* ? [] {}:
p - a numeric range for which position to complete, use shell variable 
    indexing syntax, e.g., 1, 1-2, -5, *
c - glob pattern which must match the beginning of the current word
n - glob pattern which must match the beginning of the previous word

list is the list of all possible completions.  there are a lot of codes for
various completions, check "man tcsh" for all choices.  here are some common
ones:
a - aliases
c - commands
d - directories
e - environment variables
f - filenames
n - nothing
s - shell variables
u - usernames
(...) - words from the given list
`...` - words from the output of command

suffix is pretty self-explanatory... it sticks the suffix you provide at the end
of the completion.


Here's an example from the standard tcsh complete file that breaks it down:

    complete grep	c/-*A/x:'<#_lines_after>'/ c/-*B/x:'<#_lines_before>'/\
			c/--/"(extended-regexp fixed-regexp basic-regexp \
			regexp file ignore-case word-regexp line-regexp \
			no-messages revert-match version help byte-offset \
			line-number with-filename no-filename quiet silent \
			text directories recursive files-without-match \
			files-with-matches count before-context after-context \
			context binary unix-byte-offsets)"/ \
			c/-/"(A a B b C c d E e F f G H h i L l n q r s U u V \
				v w x)"/ \
			p/1/x:'<limited_regular_expression>'/ N/-*e/f/ \
			n/-*e/x:'<limited_regular_expression>'/ n/-*f/f/ n/*/f/

Type:
> grep <TAB>
<limited_regular_expression>

This was output since you looked for a completion in the first position.

Now let's say you'd like to know what options are available with
double-dashes, just type:
> grep --<TAB>
after-context       extended-regexp     line-regexp         text
basic-regexp        file                no-filename         unix-byte-offsets
before-context      files-with-matches  no-messages         version
binary              files-without-match quiet               with-filename
byte-offset         fixed-regexp        recursive           word-regexp
context             help                regexp              
count               ignore-case         revert-match        
directories         line-number         silent              

Now try:
> grep -icA<TAB>
<#_lines_after>

which prompts us to add the number of lines after, so we pick 4:
> grep -icA4 -<TAB>
A B C E F G H L U V a b c d e f h i l n q r s u v w x 

We'd also like the filename and line number so we'll add these and then
we'd like to search for a regular expression with the -e option:
> grep -icA4 -Hne <TAB>
<limited_regular_expression>

OK, here if you're clever, you'll notice that the n/-*e/ pattern will also
complete for --file, --with-filename, --no-filename and --recursive.  Ah
well, nothing's perfect.

We can then try to complete on files with the n/*/f/ pattern:
> grep -icA4 -Hne ^skip 
file1  file2  file3

And that's that.

Here's the culmination of my knowledge.  It allows you to scp stuff to
various accounts and saves you serious RSI.  I won't explain it, I'll leave
it as a user excercise to understand:

complete scp n/-*c/'x:<cipher>'/ n/-*i/'x:<identity>'/ n/-*l/'x:<limit>'/ \
             n/-*S/'x:<program>'/ n/-*F/'x:<ssh_config>'/ n/-*o/'x:<ssh_option>'/ \
             c/-/"(c i l p r v B q C F P S o 1 2 4 6)"/ \
	     n/*@*:*/f/ \
             c@loginname1*host1*:@"(/home/loginname1/)"@@ \
             c@loginname2*host2*:@"(/users/loginname2/)"@@ \
             c@loginname3*{host3,host4}*:@"(/home/loginame3/)"@@ \
             c@loginname3*host5*:@"(/users/loginname3/)"@@ \
             c/loginname1@/"( host1.domain1.edu )"/:/ \
             c/loginname2@/"( host2.domain2.edu )"/:/ \
             c/loginname3@/"( host3.domain3.edu \
                            host4.domain4.edu host5.domain5.edu )"/:/ \
             C/lo/"(loginname1 loginname2 loginname3)"/@/ \
             p/*/f/

The complete list of tcsh completions is stored in a file named
complete.tcsh and can usually be found in the local tcsh distribution.  If
you can't find it there, it's available at tcsh.org.  Since this list
changes from system to system, depending on what version of tcsh is
running, I prefer to just keep my own copy in my home directory and source
it in my .cshrc file.

IMPORTANT: you can override completion rules and do a normal completion using
CTRL-x TAB or CTRL-x CTRL-d; this is useful if a completion is built to prevent
listing backup files, but for some crazy reason you want to access them.  And
other stuff.

login and cshrc

If you're running csh or tcsh, here's the deal with initialization
files.  There are two primary ones, $HOME/.cshrc and $HOME/.login.  Your
.cshrc is run first.  Then your .login.  However, your .login is
run only once: when starting a login shell. 

You should set your terminal type and environment variables in your .login
file since these are passed on to all non-login shells. Your .cshrc should
set your search path, set a custom prompt, set aliases and set shell
variables.

One important point that is not obvious: do not output anything from
your .cshrc file.  It's OK to output stuff, such as the date, from your
.login file, but your .cshrc file is sourced when other programs invoke
the shell.  Having .cshrc produce output will often (not always)
interfere with the operation of many programs such as less and vi. 

login vs.  non-login shells

So when you log into a shell, your .login is run and all environment
variables that are set by your .login are passed to sub-shells (which
are non-login shells) created from the login shell.  However, shell
variables (other than $path) and aliases are not passed! You can see
this quickly by temporarily moving your .cshrc to .cshrc.orig so that
there is no .cshrc file; then open an xterm and type:
   > set; echo -----; alias
All of the shell variables and aliases except for $path were defined by
system initialization files; on my Debian Linux system /etc/csh.cshrc
gets sourced (which in turn sources all files named *.csh in
/etc/profile.d)...  so all shell variables should be defined in your
.cshrc file, which is run every time you start a new shell, whether it's
a login shell or not. 

interactive vs. non-interactive shells

If you start a new xterm, you are starting an interactive shell.  That
is, the big idea is that you are starting a shell with which you will
interact! You can tell if you are in an interactive shell because
the shell variable $prompt will be set.  It will not be set for
non-interactive shells.  There are two clear examples of non-interactive
shells, i.e., shells which are started with no intention of interaction
with the shell:

(1) c shell scripts --- if you include the -f flag (fast start flag)
when running a c shell script, it will read neither your .cshrc file nor
.login file (if a login shell).  This seems like a reasonable thing
since your .cshrc file should really only contain definitions that might
be useful when interacting with the shell.  However, this may not always
be true, so leave off the -f flag if you want your .cshrc read upon
starting the script.  $path is sometimes set in the .cshrc file. 
However, this shell variable is the only one actually passed on to
sub-shells. 

(2) xterms that are called to execute a program --- if you were to
execute IDL upon initializing an xterm:
  > xterm -e idl
the xterm inherits all the environment variables and shell
variables (the ones set by your ~/.login) that exist in the shell that
launched the xterm.  The .cshrc is not sourced so, since your aliases
are not passed to the xterm, your aliases will not be available to the
program you are executing in the xterm unless this program sources
your .cshrc file.

So, the big idea is to stick only the following in you .login file:
* commands that set terminal settings (e.g., stty, tset)
  -> I've come to disagree with this... for instance, I use microemacs
     a lot and to save a file, you type CTRL-X CTRL-S.  But the default
     is to have terminal suspension on, so that CTRL-S suspends the
     terminal and you can't save the file. CTRL-Q restores the terminal.
     But there's now no way to save your changes.  So I use stty -ixon 
     to shut off terminal suspension altogether.  However, this
     does not get passed on to subshells, so you have to have this
     in your .cshrc for terminal suspension to be shut off in every
     terminal.

* commands that set environment variables (Non-login shells inherit
  environment variables from the login shell, so you need to set those
  variables only once, in .login, not .cshrc)

* commands that produce output like date... only need to see this on login

---> WARNING.  So the Linux login managers xdm and kdm do not run a login
shell, so your .login never gets run (or your .profile or .bash_profile if
your not using tcsh).  This means that xterms and konsoles launched from
the window manager never get environment variables passed to them since
they were never defined.  The suggested fix is to have your .xsession
source your ~/.login.  However, the smarter thing would be to just set
everything in your .chsrc!  Computers are fast these days; it's not that
much more work to just set everything in .cshrc.

As a note, I found the following behavior:
* SSHing into any Linux or Solaris machine left me at $shlvl=1 and my
  ~/.login was sourced like it should have been.
* GNOME sets the $shlvl=1 for all xterms and gnome-terminals open from the
  desktop, but ~/.login was not sourced so that nothing set in ~/.login
  exists in the shell.
* KDE (Debian laptop) sets $shlvl=2 for any terminals open from the dekstop
  and does not pass any ~/.login information since it mustn't have been
  sourced.
* KDE (SuSE desktop)
* Problem is probably somewhere in startkde or similar script for GNOME.
* Could start up all terminals as login shells: this would source ~/.login
  and set $shlvl=1.
* Could also set environment variable in your ~/.login:
  setenv DOT_LOGIN_SOURCED 1
  then you could source your ~/.login if you've started a non-login shell
  and you haven't yet sourced your ~/.login and that file actually exists:
  if (! $?loginsh && ! $?DOT_LOGIN_SOURCED && -e ${HOME}/.login) source ${HOME}/.login
* Finally, you should probably just set everything (except any statements
  that produce output!) in your .cshrc file.


LaTeX tricks
================
* If you want to number equations by subsection, you need to place
this chunk of code before \begin{document}:

\makeatletter
\renewcommand\theequation{\thesection.\arabic{equation}}
         \@addtoreset{equation}{section}
\makeatother


* There are strange times in life when you need to know the bounding
box of a PostScript file.  If you ever need to know this, type:

> gs -sDEVICE=bbox file.ps

The bounding box that this spits out is different than the
values listed in the ASCII header of the PostScript file.  I don't
know why.

* Spaces in LaTeX can be tricky.  Here's what to know:
  (1) When a capital letter ends a sentence, precede it by \@ to get
  the right spacing, i.e., "we plan of using array C\@. OK?"

  (2) Any period in a sentence that does not end it, should have a \ after
  it! E.g., "Hester et al.\ (1990) found dust."
  
  (3) If period followed by a ) or ", TeX will add extra space before
  next letter.  So prevent this with \ after ) or ":
  "Molecules (CO, HCN, SiO, etc.)\ are found in this cloud."

\la      : less than or approximately equal to 
\ga      : greater than or approximately equal to 
\gtrsim  : greater than or about
\lesssim : less than or about

\widetilde{P} : P with ~ above it.

Here are my macros.

In AASTeX:

*  Make sub-equations with letters, i.e. (1a), (1b), (1c):
   \begin{mathletters}
   eqnarray
   \end{mathletters}

*  Citations & bibliography

   Specify citation data inside square brackets and a citation key in
   curly braces:

   \begin{thebibliography}{} (Need the empty curlies!)
   \bibitem[author(date)]{key} bibliographic data
   \end{thebibliography}

   \citep[extra]{key(s)} : produces citation that is entirely set off
                           by parentheses
   \citet[extra]{key(s)} : allows author's name to be part of the text
   
   See natbib documentation for obscure stuff.

   Multiple citations work within a single cite, for example 

   \citep{KEY1, KEY2, KEY3, KEY4, ...} 
      (Bester et al. 1998; Garibaldi et al. 1997, 1998a,b; ...) 

   The lettering of the citations and references is done automatically. 

   \citep[hereafter B98]{KEY} 
      (Bester et al. 1998, hereafter B98) 
   \citep[e.g.,][]{KEY} 
      (e.g., Bester et al. 1998) 
   \citep[see][p. 68]{KEY} 
      (see Bester et al. 1998, p. 68) 

   Any of these can have a * affixed to make a full author list when 
   "et al." would normally be used, e.g., 

   \citet*{KEY} 
      Bester, Winters, & Alexander (1998) 

* Writeup on BIBTeX will go here.  But for now, here are my bibliography files.


EMACS tricks
================

* How do you search for just a blank line?

Well, first, you'll want use a regular expression search, M-% or ESC-CTRL-s
and the first element of the search will be ^.  Now, the next step depends
on whether you're running emacs in its own X window or in a terminal.
Either way, <RET< tells the minibuffer that you're done with the
search argument and to go search, so we can't search for the character
<RET<.

In a terminal, it's easy... just search for ^ CTRL-j ... CTRL-j being
the ASCII control character for a carriage return.

In an X window, you must use a "quoted insert"... you let emacs know you're
about to type something non-standard... that is done with CTRL-q.  So, as
you might guess, you search for: ^ CTRL-q CTRL-j

* You can get back to the main buffer when your cursor is positioned in the
minibuffer.  Just use CTRL-x o.  Sometimes you can end up with a stranded
incomplete minibuffer... just use CTRL-x o to get back to the minbuffer and
then use CTRL-g to kill the request.

* You can change the font by Shift-Left Mouse Button.

* Searching:
C-s is bound to isearch-forward.
After exiting a search, C-s C-s will look for the same string again.
C-g C-g returns you to where you started the search.
C-r is a backwards search.
Conduct a regular expression search with M C-s or M C-r.
This will let you find all occurrences of a word that begins a line:

   M C-s
   Regexp I-search: ^word

When doing a search and replace, answer with an exclamation point to replace
every occurrence of the search without asking for confirmation:

   Query replacing x with y: (? for help) !

C-w copies the remainder of the word where the cursor is currently placed.
C-y copies the remainder of the sentence where the cursor is currently placed.

If you select text with your cursor (thereby sticking it in the kill ring),
C-s M-y will pull the text from the kill ring into the interactive search.  The
text stuck in the kill ring can be from any other emacs or xterm.  However, if
from the current emacs, make sure you de-select (or un-highlight) the text
before conducting the search and yank... otherwise, the entire text from the
initial highlight to each searched word will become highlighted!  So, really,
the quick way to do a highlighted search is:

    Highlight the word or phrase.
    C-g C-s M-y

* What if you want to search for a phrase with a newline character, or
replace something with multi-line input containing a newline?

Let's say you want to find all occurences of:
<li>
<pre>
Paragraph starts here

and remove the newlines so that everything is on the same line. Just use
M-% and then search:

Query replace: <li> crtl-q ctrl-j <pre> ctrl-q ctrl-j
Query replace with: <li> <pre>

* Having trouble finding an emacs command? Look HERE

* Wouldn't you like a way to goto a specific line number?  Yes, you would.
Add this to your .emacs file:

    ;;Goto line
    (global-set-key "\C-xg" 'goto-line)

* IDLWAVE: Re-highlighting your IDL program: <C>-x h <M>-<C>-\

If you're used to re-highlighting with <C>-l (as in LaTeX editing),
you can rebind the above sequence to <C>-l by adding the following
to your idlwave.el file:

   (define-key idlwave-mode-map "\C-l"     'idlwave-indent-and-fontify)


   (defun idlwave-indent-and-fontify ()
     (interactive)
     (save-excursion
           (idlwave-indent-subprogram)
           (font-lock-fontify-buffer)))

* Over the years, I've found some oddly cool things burried in emacs:
  M-x handwrite
  M-x artist-mode
  M-x revert-buffer
  M-x isearch-complete-edit
  M-x list-colors-display
  M-x list-faces-display 


IDL tricks
==============
I use IDL a lot. I forget everything.
So HERE's what I'm forgetting.


firefox
===========
Firefox is great.  But the key bindings are a little screwy.  I've made a
crib sheet to help me get around.

Also, I have about 4 different accounts on various machines in various
states in the Union and I finally got fed up with having different
preferences for each.  So I investigated how I could set preferences for
one and then pass that account info around so I wouldn't have to waste time
keeping each up-to-date.

Firefox is highly customizable, so it would be nice to share the
customizations among your accounts on various systems.  To download all the
themes, extensions and search engines and to configure each can literally
take more than an hour.  And what happens when you find a new extension you
like?  You don't want to have to log into each account remotely and start
firefox to install this extension.

Here are some problems that we have to deal with:

(1) The user profile name will be different on each system.  All of the
user's info is stored in a directory named for the user's profile.  So, if
anything in that directory references an absolute path, we're hosed since
the paths will be different from computer to computer.  For instance, here
are various firefox paths for me:

Linux
-----
  Berkeley: ~/.mozilla/firefox/8vxhv1z1.default
    Laptop: ~/.mozilla/firefox/31q3a2fg.default
Green Bank: ~/.mozilla/firefox/xu3mgu5v.default

Windows
-------
E:\Documents and Settings\Tim Robishaw\Application Data\Mozilla\Profiles\hcjob1ih.default

(2) Some objects may be compiled for Linux and therefore will completely
choke if copied to Windows.


So, where are paths explicitly called in any of these files?

extensions.ini
-------------
lists extensions and their absolute path to their locations in extensions/

localstore.rdf
--------------
Defines default windows settings. Saved persistent values. Info about
toolbars, size, positions, etc
lists various search engine plugins and their absolute paths to their
locations in searchplugins/

xpti.dat
--------
XPCOM typelib information catalog

compreg.dat
-----------
lists a number of extensions and the full paths to the components/
directory in the each extensions directory: extensions/{}/components/


What can we do?  Well, empirically, I've determined a few important things:

(1) Deleting extensions.ini, compreg.dat, and xpti.dat does not
cause any problems. It is rebuilt by firefox with the new paths in either
Windows or Linux, so there's no good reason to even copy these over from
your primary firefox directory.

(2) Getting rid of localstore causes your preferences on the set-up of
toolbars to be lost.  But search plugins still work.  So, it's a good idea
to copy these over.

(3) Some extensions contain dynamic C libraries that are built for Linux
and therefore, when encountered in Windows XP, firefox spazzes out.  These
extensions need to be uninstalled and then reinstalled.  The firefox
extension website is clever enough to know you're visiting from Windows and
will automatically select the Windows version for you to download.  Here is
a list of the extensions that need re-installing:

* colorzilla
* espn toolbar
* mozimage
* html validator

Also, I suggest completely wiping your Windows profile... say you get rid
of an extension on Linux then move everything over to Windows... Windows
still knows about the old extension.  So, you know, wipe it clean before
copying.

This is the command I use to pack up my primary Linux firefox user
directory for exporting to other accounts:

tar zcvf ~/firefox.tar.gz -C /j/robishaw/.mozilla/firefox/8vxhv1z1.default\
--exclude=extensions.ini --exclude=compreg.dat --exclude=xpti.dat\
--exclude=Cache --exclude=lock --exclude=.parentlock --exclude=.nfs* .

When we copy over to Windows, go to SFTP, go to the firefox user directory,
CTRL-A to select all, then CTRL-left-click to deselect the useless files:
extensions.ini
compreg.dat
xpti.dat
Cache
lock
.parentlock
.nfs*


cvs
=======
consumer value store, a place to buy drugs in New England
*OR*
concurrent versions system, a place to control software revisions
   in computerland

You could save EVERY version of every paper you ever write, but boy,
that would waste A LOT of room.  CVS (Concurrent Versions System) has
a very clever way of saving just the DIFFERENCES between versions
rather than every version. Also, it makes life easy for a group of
people (like those belonging to the group 'robi'; to see which groups
you belong to, type: niscat group.org_dir | grep $USER ) to work on a
paper or program in simultaneity.

HERE's a pretty extensive and detailed set of notes
about how to set up CVS and use it wisely.  Especially with a group!


gimp 1.2
============
to prevent gimp from creating ".xvpics" directories every time
you save an image set the following preference to NEVER:

     <Toolbox> / File / Preferences / Environment / File Saving / Try
     to Write a Thumbnail File / Never


powerpoint
==============
I stayed away from PowerPoint as long as humanly possible.  Now I've given in.
There are little things that I found helpful but will never
remember.


man or astro-man?
=====================
This is pretty damn out-of-date and useless, but here's info 
that's helpful if you're on the Berkeley astronomy network...


scanning
============
* log into mimas
* open HP PrecisionScan PRO
* select color type (TrueColor: 16.7 million colors; Black & White; etc.)
* click on START A NEW SCAN icon, entire region scanned in
* select the region you want scanned in
* click on SCAN TO icon; select Corel Photo House 5
* click on PREPARE IMAGE
  * click on TRANSFORM IMAGE
    -> from here you can crop, flip or rotate your image or change the
       image size or resolution
  * click on EFFECTS
    -> here you can play with image: sharpen, change contrast, brightness, 
       make black and white, make negative
  * click TEXT
    -> add text to your image
  * try Speckle Removal
* when done, SAVE the image
* open SSH SECURE FILE TRANSFER
* click on UPLOAD (up arrow icon)
  -> select Desktop, My Documents


Exabyte tapes: reading and writing
======================================
To read an exabyte (that's 1018 bytes, for those in the
know) tape, here's what we do:

> tar xvf /dev/rmt/0

To rewind and eject the tape:

> mt rewoffl

(mt: magnetic tape control; rew: rewind, offl: offline (eject!))

To write to a tape, just go to the directory you want copied and: 

> tar cvf /dev/rmt/0 .

There are more complicated things you can do with a tape, but I doubt I'll ever
need to.  But Steve needs to, so check his notes if that time does ever come.
Also look here to see if there are more details.


DLT
=======
Pop in a DLT into the drive.  Close the hatch.

Push the SELECT button until COMPRESSION and 40.0 (GB) are selected.
This didn't work the first time I used a DLT so I got stuck with an
uncompressed 10.0/15.0 GB tape.  Ah well.

Now follow instructions HERE.

To get the damn thing out, you have to push the UNLOAD button.  Then
wait a few minutes.  Then lift the door to make the tape pop out.


my linux desktop
====================
I got a linux dekstop and I took some notes while setting it up.  These should
be pretty useful for reference.


laptop
==========
I just set up two dell laptops (a latitude d800 and latitude d600) to be
windows/linux dual-bootable with a shared partition.  This was quite a learning
experience and I learned everything I know about it from fitz.  In case I ever
have to do it again, here are my notes.


miscellany
==============

login from outside of Berkeley

PuTTY

directory hierarchy

Now that I'm trying to maintain a laptop and desktop I'm finding it pays to be
wise when it comes to setting up my directory structure.  After a few
philosophical discussions with carl and fitz, I've decided the right way to go
is to have project directories that store my code, scripts, and sundries, and to
have a symbolic link from this directory to the relevant data which will be
stored under a /data directory off of my main directory.  This will be the
location of the calibrated and processed data.  This directory will in turn have
a symbolic link to the corresponding raw data set that will live off of the
/data/raw directory.  The big philosophical idea here is that I will often want
to copy a branch of a project either to my laptop or to an observatory, but
there's no way I'm going to want all the data corresponding to this project!  I
might want a small set of these data and then I can select it separately from
the project directory.  Say I copy the code to Green Bank; well, the data live
there permanently, so I'll I need to do is add a symbolic link to their
permanent home there.  This comes with the price of having to traverse symbolic
links, which, if I'm conscious of this, can be made easier by remember to use
pushd (which I've aliased to pd) to add the traversal steps to the directory
stack.... this will make getting around a little easier.

New stuff...

When writing an alias or a csh script, you have to be constantly aware of
special characters.  Here's a brief listing of the important points:
\ - a backslash turns off the meaning of special characters
'...' - single quotes turn off the special meaning of all characters between
them except for ! which still acts like a history operator
"..." - double quotes shut off special characters except for !,$,`` which still
allow history, variable or command substitutions.  So "" is weaker than ''.
Quotes can quote each other: "'" or '"'
A \ is the only way to turn off !
You can turn off ! and ` with \ in ".." but not $, need single quotes for $.
You cannot use a single quote, even escaped, inside a pair of similar quotes, so
these won't work: "\"" '\''

You can repeat a command N times: repeat N command

You can piggy back expansions: {1,2,3}{4,5,6} -> 14 15 16 24 25 26 34 35 36

This one's awesome: if you want a command's ouput redirected to BOTH the screen
AND a file, use the command "tee":

> command | tee file_name

To prevent the shell from grabbing duplicate commands when using
up-arrow-callback (that is, if you use ls 5 times in a row, why would you want
to cycle through all of these in your history?) use this in your .cshrc:
set histdup=prev

if you type something like "rm d*pro" and you'd like to double check just what
that glob pattern is going to include, you can use the binding for list-glob,
which happens to be CTRL-x g for the emacs bindings:
> rm o*pro
oplotbeam.pro   oplotscale.pro

If you actually want to expand the glob pattern right on the line, use the
binding for expand-glob, which in emacs is CTRL-x * ...
> rm o*pro
becomes
> rm oplotbeam.pro oplotscale.pro

Deleting a word backwards is: CTRL-x BKSPC.

Doing a which on a command: ESC-?
Clearing the screen: ESC-CTRL-l
You can bind complete-word-fwd and complete-word-back so that you can use these
to cycle through completions of whatever prefix is to the left of the
cursor.  I prefer Meta-Left and Meta-Right for these:
bindkey "^[^[[D" complete-word-back
bindkey "^[^[[C" complete-word-fwd
So if you have three files, a1 a2 a3, and you type: 
> ls a-TAB
a1  a2  a3
Now type Meta-Right to cycle forward through the completion options and
Meta-Left to cycle backward.

I found something completely bizarro using exceed to display a PostScript image
I had created in IDL with gv.  The PostScript image was created using hardware
fonts, which look really nice compared to the standard vector fonts that IDL
produces.  However, when running Windows XP and trying to display this image
with gv I was finding that only part of the image had the font displayed
correctly.  Very mysterious.  I can't explain why this works, but by setting the
-antialias flag for gv, the image is displayed correctly.  It should be noted
that xv displayed this image properly, but of course, some versions of xv can't
display PostScript images, so it's good to know about the kludge to fix gv.

------------------------

ANIMATED GIFS...

It was really easy to make an animated GIF using gimp.  First, convert
all your images to GIFS.  You can use command-line command "convert" to
get your images all the same size.  The open your images in gimp and try
to align them properly if there's some offset between them.  Try to crop
them all to the same size.  Then go to the first image and click "New
Layer" under the Layer menu (right click to get the tools); then go to
the second image, right click on it, select "Copy"; now go back to the
first image, right click and click "Paste"; now go to the floating layer
in the Layers GUI and right click on it and select "Anchor Layer"; now
is a good time to rename the layers something sensible, like Frame 1 &
Frame 2.  Obviously, it's pretty easy to do this for more than two
frames.  When you're all set -- very important -- select "Image - Mode -
Indexed" and select "Generate optimum palette" and for Colour dithering:
"None"...  otherwise you're images will look like ass.  Now select "Save
As" and select GIF; it will ask if you want to flatten or save as
animation, select "Save as Animation" and click "Export"; now select the
delay between frames (500 ms is pretty good) and select "One frame per
layer". 

ACCESSING CalMail from pine...

I needed to know just enough to be able to access my CalMail messages with pine
from my astronomy account.  When I go away, I forward to CalMail, but when I get
back to the department, I use pine again.  I want to be able to store the
CalMail messages in my pine folders.  Here're the steps I took to be able to do
this in pine:

* Hit M-S-L-A and enter Nickname: CalMail IMAP E-Mail; Server:
calmail.berkeley.edu/ssl; CTRL-X to save, then exit.

* Hit M-S-C, scroll down to Folder Preferences Section and select [X]
enable-incoming folders; then E-Y-Q to quit.

* Start pine again, hit L and go to Incoming Folders; hit A to add CalMail
floder:  Enter: {calmail.berkeley.edu/ssl}inbox and Nickname: CalMail Inbox

* Now grab the mail from CalMail inbox and save them in your Mail folders.  When
you're done, M-S-C-L and delete the CalMail folders.


go home