MH & nmh: Email for Users & Programmers

May, 2006

The mhpath Command

Because users can change their MH directory structures completely, your shell programs shouldn't assume anything about the locations of folders or the names of their MH directories. Instead, use mhpath to get this information.

Here are some examples:

    $ folder
           inbox+ has 1123 messages (   2- 1147); cur=  15.
    $ mhpath
    /u/ehuser/Mail/inbox
    $ mhpath last:2
    /u/ehuser/Mail/inbox/1146 /u/ehuser/Mail/inbox/1147
    $ mhpath new
    /u/ehuser/Mail/inbox/1148
    $ mhpath all
    mhpath: more than 998 messages
    $ mhpath +somefolder
    /u/ehuser/Mail/somefolder
    $ mhpath +
    /u/ehuser/Mail
    $ folder
           inbox+ has  1123 messages (   2-  1147); cur=  15.
    
With no arguments, mhpath gives the full pathname of your current folder. If you give message numbers, sequences, or ranges, you'll get the full pathname of each message. The special argument new gives you the pathname that a new message in the folder would have -- useful if you're creating a new message. If you give a folder name, mhpath gives the full pathname of that folder but it doesn't change the current folder. The folder doesn't have to exist yet unless you want the paths of messages in the folder. An argument of just a plus sign (+) gives the path of the MH directory itself.
CAUTION: In MH 6.8.3 and before (and possibly after), mhpath won't print more than 998 pathnames. (The limit is the system constant MAXARGS, which is assumed to be the maximum number of arguments to the exec() system call.) If you ask for more, it gives the error shown in the example above. This is a serious problem for scripts that need to be robust and portable.

Luckily, nmh's mhpath doesn't have that problem. It still can't accept more than MAXARGS command-line arguments, of course. But it can accept MH message ranges like 1-2000 or all that expand into more than 998 messages -- and, in the same way, it can expand sequences that have more than 998 messages.

If you're using MH, or writing scripts that might be used under MH, here are a couple of workarounds. The first may work, some day, in later versions of MH or nmh; it uses the undocumented (and non-working!) format escape named (folder). The second works now and should be portable; it uses sed to add the current folder pathname onto each message number:

      $ scan -format '%(folder)/%(msg)' all
      scan: "%(folder)": format compile error - unknown function
      scan:          ^
      $ scan -format '%(msg)' all | sed "s@^@`mhpath`/@"
      /u/ehuser/Mail/inbox/2
      /u/ehuser/Mail/inbox/3
         ...
      /u/ehuser/Mail/inbox/1147
      
(The all actually isn't needed because scan scans all messages by default.)

You'll almost always use mhpath with command substitution (the backquotes). For efficiency, you can run mhpath once at the start of the shell script to grab things like the location of the user's MH directory and store that information in a shell variable.