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 ===============
Every now and then, I get a file that is filled with a highlighted ^M at the end of EVERY line... this is windows type of thing and the document can be converted to a UNIX-readable document with the command dos2unix.
This one gets me often: if you try to rsync a file with a colon in the name to a remote destination, it will get confused and think the file is a hostname with the destination after the colon. This will confuse rsync: > rsync -avz file:1:2.fits me@host.com:/path/to/dest The trick is to add a ./ before the filename... > rsync -avz ./file:1:2.fits me@host.com:/path/to/dest
xargs is great. It takes the standard input and builds then executes command lines. So if you want to search through all .pro files for the variable "angle": > find . | grep "\.pro"$ | xargs grep angle This is way, way faster than executing a command via -exec! This will fail if filenames with spaces are encountered. You can get around this by having find print out the filename followed by a null character rather than a space (the -print0 flag does this) and telling xargs that the names are terminated by a null rather than the space (the -0 flag does this): > find . -print0 | xargs -0 grep word > find . -print0 | xargs -0 file | grep MP3 All of a sudden in 2006, within days, I found a number of programs that I had upgraded were creating directories with spaces in their names: KDE, Adobe, Macromedia, IDL, and as always, mp3s.
You can make a directory hierarchy in one fell swoop with -p: > mkdir -p root/trunk/branch/leaf
You can easily rename a bunch of files using rename: > rename .htm .html *.htm
There are two types of if statements in csh/tcsh, the one-line version if (condition) command and the block version if (condition) then command endif The problem with the one-line version is that command cannot use an alias, which is not true in the block version. The problem with the block version is that it cannot be used to define an alias! So what if you want to define an alias that uses an if statement? The answer, learned the hard way, is to use eval to evaluate the command: if (condition) eval "command" Here is an example which checks to see if the file \gimp (this gets the fully qualified path to gimp) exists and is executable, and if so, runs gimp and sends any arguments you include to gimp. All gimp's terminal output is thrown away to /dev/null. And finall, we run all this in the background. Whew: alias gimp 'if (-x `which \gimp`) eval "\gimp \!* >& /dev/null &"'
Beeping was driving me nuts. So I shut it off permanently. You can do this for tcsh by typing "set nobeep", but the way to shut off the beep for all applications handled by the Xserver is to include this line in your .xinitrc file: xset -b.
carl showed me how to use the --side-by-side feature of diff. it is pretty freaking awesome. I find making the xterm pretty damn large and then using --side-by-side (-y is the shortcut) in combination with --width=columns (-W columns is the shortcut) to make the total number of columns a little larger. > diff -yW 180 file1 file2 A few other useful options... -B : don't tell me about blank line differences... -i : ignore changes in case
pushd/popd Lately I've been finding that I've had a lot of data living on other disks. So I try to be clever by making symbolic links from my project directories to the data directories. But when I cd across the link and then move down into the data hierarchy, I find that I'm stranded on the other disk; in order to get back to my project directory I have to cd to its fully-qualified path. tcsh has the nice feature where "cd -" moves back one level and even traverses symbolic links. However, that's of little use if you traverse the link and then move down in the tree. So if you can anticipate crossing a symbolic link and have any desire to return, you should train yourself to use pushd and popd. The big idea is that you can keep a running tab on what directories you have visited if you stick them on the "directory stack"... this is accomplished by using pushd: > pushd dir_name To view the directory stack: > dirs Use -v to print entries one per line and give their stack positions. > dirs -v Use -l to make force the expansion of ~. > dirs -vl To clear the directory stack: > dirs -c The default behavior of pushd and popd is to print the final directory stack. You can shut this off by putting this in your .cshrc file: set pushdsilent You can override this by using -p. Let's look at an explicit example. We have a directory hierarchy: /a/level1/level2 We have directory /b in which we make a symbolic link to /a/level1/: /b/level1 -> /a/level1/ Now, we go to /b... /home> cd /b And we cd across the symbolic link... /b> cd level1 Now we can just use cd - to get back to where we came from... /a/level1> cd - /b> Ok, but what if we cross the symbolic link and then move one directory down... /b> cd level1 /a/level1> cd level2 /a/level1/level2> cd - /a/level1> Now we've lost all information about where we came from before crossing the link. So instead, let's try this with pushd: /a/level1> pushd /b /b> pushd level1 /a/level1> pushd level2 Now let's look at the directory stack that we've built up... /a/level1/level2> dirs -v 0 /a/level1/level2 1 /a/level1 2 /b So we can go back sequentially by pulling one directory at a time off the stack using popd... /a/level1/level2> popd /a/level1> popd /b> popd popd: Directory stack empty. So there's nothing left in the stack. That's cool, but maybe you want to keep the stack around rather than wiping it out. If you build the same directory stack again, now try just inputing pushd... /a/level1/level2> pushd -pv 0 /a/level1 1 /a/level1/level2 2 /b /a/level1> pushd -pv 0 ~/a/level1/level2 1 ~/a/level1 2 ~/b /a/level1/level2> So pushd all by itself just swaps the top of the stack and the 1st entry in the stack. It's just like typing "cd -" over and over. Unlike popd, pushd does not remove the top of the stack. So how would we use pushd to get back to the /b directory? We can do it by just rotating the desired stack level to the top: /a/level1/level2> dirs -v 0 ~/a/level1/level2 1 ~/a/level1 2 ~/b /a/level1/level2> pushd -pv +2 0 ~/b 1 ~/a/level1/level2 2 ~/a/level1 So, this is really useful if you're planning on doing some serious disk cruising. To save RSI, I'd also alias pushd to pd (kinda like cd)... alias pd pushd when doing history substitution, =n refers to the nth directory in the stack, while =- refers to the last directory in the stack
when switching from solaris to linux, I found it very disturbing that when listing files, "dot files" were sorted with the other files rather than alphabetically AND *before* the rest of the files. I prefer the latter sort order and the way to achieve this in Linux is by setting: setenv LC_COLLATE C Stick this in your .cshrc file.
list the size of all directories but don't print subdirectories... > du -ks */
showrgb shows a list of rgb values for color names.
saoimage software: ds9
in tcsh, retrieve the last word of the previous line with M-_: > ls thisfile > rm M-_ rm: remove `thisfile'?
file sizes are listed in bytes when you use ls. but du lists file sizes in 512-byte units (usually called a block, I think.) you can list file sizes in 1024-byte units with du -k: > \ls -l 158-39.n.a.fits -rw-r--r-- 1 robishaw other 18069120 Jun 5 2002 158-39.n.a.fits > du -k 158-39.n.a.fits 17672 158-39.n.a.fits (Well, 18069120/1024 = 17645, so, well, close, but not perfect.)
apparently, you can use the program sox to convert audio files to .au files.
if you're running tcsh and you want to learn more about tab completions and their definitions, check out: /usr/local/tcsh-6.07.02/complete.tcsh
if you want to have cd .. behave just like cd - (rather than cd $cwd/..): set symlinks=ignore
geometry calls are structured -geometry WIDTHxHEIGHT+XOFF+YOFF +XOFF: The left edge of the window is to be placed XOFF pixels in from the left edge of the screen -XOFF: The right edge of the window is to be placed XOFF pixels in from the right edge of the screen. Similar for +YOFF, -YOFF.to find the jobs that are running from a terminal: > jobs -l
get lots of information about your terminal settings: > stty -a
psutils: psnup: puts mutiple pages onto each sheet of paper. > psnup -6 -m1cm -b0.2cm -d -pletter infile.ps outfile.ps -number_of_pages: the number of pages to fit onto a sheet -m: leave a margin around whole page -b: leave a margin around each page on sheet -d: draw a border around each page on sheet psbook: rearrange pages in PostScript file > psbook -s4 infile.ps outfile.ps -s: number of sides which will be folded and bound together (multiple of 4) psselect: select pages from a postscript file > psselect -e -r infile.ps outfile.ps -e: select even pages -o: select odd pages -p: a comma separated list of pages (ex: 1,3,4-8) to be selected The prefix '_' indicates page number relative to end of document -r: outputs selected pages in reverse order psmerge: merge several PostScript files into one > psmerge [-o outfile.ps] [file1.ps file2.ps file3.ps ...] psresize: rescales and centers a document on a different size of paper epsffit: fit encapsulated PostScript file into bounding boxsox: deals with tons of audio files. read documentation someday: /usr/local/soxnumerical recipes programs (fortran and c) live in: /usr/local/nrtop. when in interactive mode (default): n: change number of processes displayed u: display only processes owned by a specific user o: change sort order (time, cpu, size, res) i: toggle display of idle processes h: show summary of commands q: quitremind yourself about how regular expressions work: > man regexpchanges in the environment of subshells are not passed back to the parent shell! So you can change or set environment and shell variables, or even change directories in a c shell script and not worry about affecting the parent shell.you could start an xterm as a login shell with the -ls flag.
use expansion, it's cool: > echo /{hvc,fenway,milkyway,hydrogen}/robishawwhen writing a c shell script, use the -n option while testing; this parses but does not execute commands.to test history completions, set the c shell variables echo and verbose: set echo verbosedomainname : display name of current domain
cd - : sends you back to the directory you were just in.
do1 && do2 -> won't do2 unless do1 is successful do1 || do2 -> if you can't do1 then do2when trying to do a long listing on a directory to get its status: \ls -ld directorynamewhen running OpenWin, wsinfo gives lots of useful workstation info, including virtual memory in use.fold lines after xx characters from an input file: fold -s -xx filename
To find out who someone is: > listusers -g group_name > listusers -l login1,login2,login3look for registered domain names: whois domain
locate binaries for a command: whereis command unlike which, returns duplicatesto make record of terminal session: script -a filename type exit to stop the record.display disk quota information: quota -v $USER
check the first xx lines of a file: head -xx filename check the last xx lines of a file: tail -xx filenametr command: add, delete, replace characters
list files in increasing time order: ls -ltr
To find which fonts are available for your xterm, type xlsfonts.
To find the printers available to your machine: % lpstat -vTo find the visual classes available to you, type xdpyinfo.
To find useful info about a window (position, visual class, etc.) type xwininfo and then click on the window you're interested in. To find info on the root window (background), use the -root flag.
If cursor is on a word, M-d will delete to end of line. M-<BACKSPACE> removes last word.
If you want to get rid of an alias, use unalias.
If you want to run more than one command from the prompt separate them by semicolons: % clear; ls; echo "bingo"To find which environment variables have been set, type env, setenv, or printenv.
To find the default printer, lpstat -d. To find the available printers, lpstat -v. To find all your jobs, lpstat -u $USER.
When running find or grep, you may be recursively looking through a directory. If there are a sea of directories which you do not have permission to read, this error will be sent to standard error and will be output to your screen a zillion times. The solution in c shell is to send the standard output to /dev/tty (or some file) and the standard error to /dev/null: ( find . > /dev/tty ) >& /dev/null
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
================
Indentation doesn't work in minipage mode, but you can set \setlength{\parindent}{4ex} after the minipage declaration so that indentation will work properly.There's a nice document class called "seminar" for making slides. It automatically produces landscape slides and it works great for importing into PowerPoint. There are some nice instructions in The LaTeX Graphics Companion and here. \documentclass{seminar} \usepackage{graphicx,amssymb,semcolor} \begin{document} \pagestyle{empty} \slideframe{none} \begin{slide} % SLIDE 1... \newslide % SLIDE 2... \end{slide} \end{document} Now, xdvi defaults to showing a portrait size A4 page; so if you don't pass any flags, you will see the edge of the paper running down your slide. You need to tell xdvi to. As a note, people in the United States and Canada use US Letter paper, which is 8.5x11.00 inches. The rest of the world uses A4 paper, which is 8.26x11.69 inches. Guess it makes sense then to cater to the rest of the world and ave A4 be the default. So, uh, be aware of this. To get xdvi to behave for US and Canadian citizens, you need to pass the -paper flag set to "usr" which means "us rotates"... (for portrait printouts, "us" will work.) > xdvi -paper usr slide.dvi Now, how about printing to PostScript? If the PostScript file believes it's portrait but the bounding box is landscape, you will have a weird effect when browsing through pages of this document... the stuff that lives to the right of the portrait boundary will just pile up into a big mess. I saw this happen to Carl because he aliased dvips to have the flag -t letter, which forced the paper size to be portrait US letter. Go ahead and try it: > dvips -t letter slide.dvi > gv slide.ps That isn't what we want. Just go ahead and dvips it: > dvips slide.dvi > gv slide.ps
There's a neat way to embed an image alongside text, that is, to let the text run alongside the image in order to not waste space. Use the wrapfig package: \usepackage[verbose]{wrapfig} And here's an example of the usage, where we stick the image on the right of the text: \begin{wrapfigure}{r}{3.0in} \begin{center} \vspace{-0.4in} \includegraphics[width=2.4in]{image.ps} \caption{This image is embedded in text. \label{image}} \end{center} \vspace{-0.2in} \end{wrapfigure}
* 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