Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I use this line for images in my mailcap:

image/*; eog %s &;

but mutt immediately deletes the temp file and eog can’t load it.
When I remove the & mutt waits for eog to be closed until it escapes from the command line.

share|improve this question
add comment

2 Answers

up vote 1 down vote accepted

Here's what I use:

.mailcap:

application/*; mkdir -p /tmp/mutt \; cp %s /tmp/mutt \; xdg-open /tmp/mutt/$(basename %s) &

.mutt/muttrc:

folder-hook . `rm -f /tmp/mutt/*`

Every time an attempt to open an attachment is made, it's copied in a dedicated temp directory and the copy is opened.
Every time you start mutt, any lingering copies are cleaned up.

You may or may not need the & at the end, depending on the command you used. (Some versions of xdg-open are blocking, while others are not.)

Needless to say, you can use this with any command. xdg-open is just a convenient one-stop handler.

share|improve this answer
    
This is a cool general way to replace mailcap! Thanks! –  Profpatsch Jan 17 at 11:02
    
I needed the & after xdg-open. Can’t hurt to have it there in any case, right? –  Profpatsch Jan 17 at 11:06
    
Maybe you could make a question: How to replace mailcap with xdg-open? and copy that answer over. I’m sure there are some people with that question. –  Profpatsch Jan 17 at 11:09
add comment

You could use a wrapper command that:

  1. renames the file
  2. runs the viewer in background
  3. cleans up when the viewer has returned instead of letting mutt do it.

Something like:

#! /bin/sh -

TMPDIR=$(
  mutt -D 2> /dev/null |
    awk -F\" '
      $1 == "tmpdir=" {
        gsub("~", ENVIRON["HOME"], $2)
        print $2
        exit
      }'
)
[ -n "$TMPDIR" ] || exit
export TMPDIR

nargs=$#
nfiles=0
for i do
  case $i in
    ("$TMPDIR"/?*)
      new_file=$(mktemp -ut "XXXXX${i##*/}") &&
        mv -- "$i" "$new_file" &&
        nfiles=$(($nfiles + 1)) &&
        set -- "$new_file" "$@" "$new_file" &&
        continue
  esac
  set -- "$@" "$i"
done

run_command() (
  shift "$(($nargs + $nfiles))"
  exec "$@"
)

(
  run_command "$@"
  while [ "$nfiles" -gt 0 ]; do
    set -- "$@" "$1"
    shift
    nfiles=$(($nfiles - 1))
  done
  shift "$((2*$nargs))"
  rm -f -- "$@"
) &

And put something like:

image/*; muttv eog %s;

Where muttv is that script above.

The above makes no assumption on where the filename(s) appear(s) in the list of arguments or what character they contains... Which is why we first ask mutt what its tmpdir is (so we use that to determine what are the files to view).

In most cases, it would be overkill though, and as Gilles points out may not work if tmpdir is specified as relative to your mailbox folder.

A simpler one would be:

#! /bin/sh -
nargs=$#
eval "file=\${$nargs}"
newfile=$(dirname -- "$file")/new-$(basename -- "$file")
while [ "$nargs" -gt 1 ]; do
  set -- "$@" "$1"
  shift
  nargs=$(($nargs - 1))
done
shift
mv -- "$file" "$newfile" || exit
(
  "$@" "$newfile"
  rm -f -- "$newfile"
) &

Replace mv with cp if you don't want to touch the original file provided by mutt.

share|improve this answer
    
Gosh, did you just write that from scratch? It took me 15 minutes to understand what you are doing and even now I’m not sure about how some parts work exactly. –  Profpatsch Feb 20 '13 at 0:19
    
Fails with my .muttrc because tmpdir="=tmp". Why not grab the directory from the file name? –  Gilles Feb 20 '13 at 19:53
    
@Gilles, good point about the "+", "="... The whole point was to get tmpdir from mutt so we know which of the arguments is the file name. The whole thing is a bit overkill though anyway as in 99% of the cases the filename is going to occur only once and be the last argument, and we can just rename it to new-$original –  Stephane Chazelas Feb 20 '13 at 19:58
    
Another point is that this entry script isn't always called on behalf of mutt, it could be called in circumstances where the file isn't a temporary file and must not be deleted. (I often call see on the command line, I don't expect it to remove the file, even if it's in /tmp!) Solution: make a hard link. –  Gilles Feb 20 '13 at 20:03
    
@Gilles, I thought of the hardlink, but for mutt, it doesn't work, because after running the command, mutt truncates the file before unlinking it. (open with O_TRUNC and close, I did verify it). –  Stephane Chazelas Feb 20 '13 at 20:30
show 2 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.