MH & nmh: Email for Users & Programmers

May, 2006

Writing Shell Scripts for MH

Our first example is a simplified version of the shell program called fols. It lists the names of your MH folders in columns. The program has just one line:

    folders -fast -recurse $* | pr -l1 -4 -w78 -t
    
Here's a comparison of fols and the standard folders -fast -recurse. Besides being easier to type, fols uses less space on the screen.
    % folders -fast -recurse
    drafts
    drafts/DELETE
    inbox
    inbox/DELETE
    mh-users_ADD
    mh-users_ADD/DELETE
    mh-workers_ADD
    reference
    reference/DELETE
    % fols
    drafts             drafts/DELETE      inbox           inbox/DELETE
    mh-users_ADD       mh-users_ADD/DELET mh-workers_ADD  reference
    reference/DELETE
    
You can see that the end of one of the subfolder names is cut off. There are a few ways to fix that -- you'll need to add another line or two to the shell program. But this is an introduction, so let's skip that for now. (See the improved fols in the Section Explanation of fols.)

Our second program, incs, uses inc to incorporate new mail messages, then uses show to display them all. If there were no messages, it doesn't run show:

    % incs
    inc: no mail to incorporate
        ...Later, after some mail comes in...
    % incs
    Incorporating new mail into inbox...
      45+ 02/04 boris@kremvax.kgb  UNIX question<<Comrade Emma, I ha
      46  02/05 Jim Bob Smith      Re: Encapsulation destroying good
    (Message inbox:45)
    From: boris@kremvax.kgb.su
    To: ehuser@mysun.xyz.edu
        ...
    
incs uses some more advanced features of the shell, but it's still pretty simple. It looks like this:
    % cat incs
    #! /bin/sh
    # $Id: incs,v 2.0 92/08/02 18:45:50 jerry book2 $
    ### incs - incorporate messages, then show them
    ### Usage: incs [+folder] [-inc options]
    #
    #   incs DOES AN inc, THEN A show OF ALL MESSAGES inc'D.  IF YOU
    #   SET THE ENVIRONMENT VARIABLE $INCSHOW TO THE NAME OF A PROGRAM
    #   THEN incs WILL USE THAT PROGRAM INSTEAD OF show.

    temp=/tmp/INCS$$
    stat=1  # DEFAULT EXIT STATUS; RESET TO 0 ON NORMAL EXIT
    trap 'rm -f $temp; exit $stat' 0 1 2 15

    # ONLY SHOW MESSAGE IF inc ACTUALLY INCORPORATED ONE.
    # BE SURE inc CHANGES CURRENT MESSAGE (OVERRIDE .mh_profile):
    if inc -changecur $* > $temp
    then
        cat $temp
        ${INCSHOW-show} cur-last
        stat=0
    fi
    
(You can also get the script from this book's online archive. It's at examples/mh/bin/incs.) I won't explain all the script here. But you can see that with only nine lines of code (and nine more lines of comments), you can write a very useful program. If you're interested in just writing basic one line programs like fols, the following steps should help you. To write more complex scripts, though, get a good book on shell programming.

Here's how to write the fols shell script. You'll use these steps for longer scripts, too.

  1. First, at a shell prompt (%, $, or whatever), type the command you'll be using in the script to be sure it works:
          % folders -fast -recurse | pr -l1 -4 -w78 -t
          
    A list of your folder names should come out in columns as you saw at the start of this chapter. (The -l1 is lowercase letter "l" followed by the digit 1.)
  2. Start your favorite text editor (emacs, vi, whatever) on a new file named fols.
  3. On the first line, starting at the left margin (column 1), put:
          #!/bin/sh
          
    That tells your system to use the Bourne shell (/bin/sh) as an interpreter. (If you have problems with this, the Section How Does Your System Execute Files? shows how to be sure that it works on your system. If #! doesn't work, you can probably leave the first line blank.)
  4. On the second line of the file, write the command line you want to run. To run several command lines, put one on each of the following lines:
          folders -fast -recurse $* | pr -l1 -4 -w78 -t
          
    (The $* pulls in a copy of the script's command-line arguments, if there are any.)
  5. Save the file and leave the editor.
  6. Next, you need to make the shell script you just wrote executable. The chmod (change mode) command is used to change permissions on a file. The plus sign (+) makes the file executable. Type the following command:
          % chmod +x fols
          
  7. If your account uses the C shell, you'll need to reset its command search table. To do that, type:
          % rehash
          
  8. Finally, try the script. Just type its name and it should run:
          % fols
          
    If that doesn't run, your current directory may not be in your shell's command search path. In that case, try this:
          % ./fols
          
    and, if you need to, read the Section Making a bin Directory, Setting Search Path.
That's how you write a shell script.