Explanation of rmmer

The Section Improve rmm: use rmmer gives an overview of this script. Here is the rmmer script (you might want to open it in a separate browser window). To install it, first see the Section Programs in This Book's Archive and create the file rmmer. You'll probably want to extract the three hard links to the file too: rmmer_1, rmmer.noask, and rmmer_1.noask. If you give tar all four names, it will create the links automatically; otherwise, make the links with ln. Finally, set up a cron or at job to actually remove the "deleted" messages. The Section Periodic Cleanup, Checking, etc. with cron and at has more information.

Edit the script file; check the settings of the variables mhbin, mkdir, and touch to be sure they're right for your system. (And after you edit the script, be sure that your editor hasn't broken the link between the script's four names. Use ls -l and check that the link count is still 4.) Also, uncomment the echo line that takes care of the unfortunate difference between the System V and Berkeley versions of echo. They have different conventions for telling echo not to print a newline. For System V, the script needs a \c, like this:

    echo "rmmer: remove 22 in +archive? [ny](n) \c"
    
Berkeley UNIX needs this instead:
    echo -n "rmmer: remove 22 in +archive? [ny](n) "
    
For Berkeley, $echo is echo -n and $nnl is empty. On System V, $echo is plain echo and $nnl is \c. On systems like SunOS with an echo command that handles both System V and UNIX, we set a PATH with /usr/bin first -- this makes a Berkeley echo.

The case $0 statement tests the name that the script file was called with and sets two variables that change the script's behavior. For example, if a user has rmmproc: rmmer in her MH profile, she wants the program to move messages into a subfolder with a name like @DELETE. Other users may use the same script and want it to do something else. Because MH can't pass arguments to the rmmproc from the MH profile, this trick lets the same script file work in four different ways.

Another important technique for shell programming is to create temporary MH profile and context files. The Section Multiple MH Sessions has background on this technique. In this script, the temporary MH profile does more than customize the way that the script works (overriding anything in the user's MH profile). It also avoids infinite loops by setting the rmmproc -- during the script -- to /bin/rm (instead of the rmmproc set by the user, which is this script). The refile command at the end of this script will move the message to the DELETE folder, then it will use the rmmproc to remove the message from the current folder. So, the final refile will use /bin/rm. Newer versions of MH have a refile -rmmproc switch, but older versions don't; this trick makes the script work on all versions of MH.

The mh-sequences: entry in the temporary profile sets private sequences to keep the final refile from changing the current message number. This is important because the default rmm -- without an rmmproc -- doesn't change the current message. The rmmproc shouldn't change that behavior.

The temporary context sets the current folder name so refile can find the messages in this folder. Without a Current-Folder: entry, refile would default to inbox.

Finally, the script resets the value of the MH and MHCONTEXT environment variables to our temporary versions of those files. Because of the way UNIX environments are set, this will only reset those environment variables for the rest of the rmmer script (basically, during the refile command in line 82). See the Section Changing the MH Environment.

When you type rmm, MH sets its current directory to the folder where messages are being deleted before it starts the rmmproc running. So this shell script can work in the folder directly; it doesn't need a pathname for operations on subdirectories with relative pathnames (like the tests for existence and creating the directory named in the moveto variable).

The script tests to see if the subfolder named DELETE (actually, $moveto) exists; the subfolder will be a subdirectory of the current directory. (This is only done for subfolders because there can be a lot of them. The script should be able to make new DELETE subfolders because an MH user can easily add new folders that'll need their own subfolders. I think that if the program was called as rmmer_1, the user should create a +DELETE folder by hand. That one-time operation is more efficiently done by hand than to add the extra code to check for a +DELETE every time this program runs.)

If there isn't a DELETE subfolder, the script creates it with mkdir. If the script had let refile create the subfolder at line 82, it would cause trouble for users of front-ends likexmh. xmh wouldn't display the prompt create folder? from refile, and xmh would hang there forever, waiting for you to answer. (Actually, that only causes trouble for xmh users who start xmh from a shell prompt. If xmh doesn't have a controlling terminal, then refile won't either; it won't prompt for an answer and xmh won't hang.)

The square brackets ([]) in line 62 are another way to run the test command. If your system doesn't have this, replace the [ with the word test and delete the ].

Lines 69-77 test to see if there's a .rmmer.ask file in the current directory (current folder), if the standard input is coming from a terminal (so you can answer the prompt), and if the ask variable was set to ok in lines 24-27. If all those are true, it prompts you and quits if you answer anything but upper or lower-case "y". When rmm starts its rmmproc, it has already translated sequences into message numbers -- so the rmmproc doesn't have to. For instance, the command:

    % rmm first:2 cur 26
    
might leave the numbers 1 3 12 26 in $*.

If the script hasn't quit at lines 58 or 75, it's time to remove the messages. Line 81 runs the touch program to update the last-modification "timestamp" of the message files. That's for the find that cleans up the folder (see the rm_msgs scripts in the Section Remove Messages from rmmer) -- it should delete messages that were not modified in the last n days. Renaming a file doesn't change its modification time, so the messages might be months old, and deleted the next time find runs, without a grace period. (If the find used the last-access time (-atime) instead, it might never delete the messages because each scan of the folder updates the last-access time of each message. Using the ctime won't work right if the message has other links which cause the file's ctime to be updated sometime before the link in DELETE is removed.)

Whew. If you think that seems like a lot of work and that using plain refile would be easier, here are three reasons:

  1. As the rmm manual page suggests, a shell alias could run refile without having this problem. But as explained in the Section They Won't Always Work, other MH commands (including refile itself) couldn't use your alias.
  2. refile changes the current message number. The generic rmm command doesn't.
  3. Using plain mv to "move" the messages won't update the MH message sequences.