diredでinteractive関数が使えると便利なことがある。

こんな関数をinit.elなどに書いておく:

(defun dired-M-x (cmd)
  (interactive
   (list (completing-read "dired-M-x: "
                          obarray
                          (lambda (v) (fboundp v))
                          t)))
  (dolist (f (dired-get-marked-files)) (funcall (intern cmd) f)))

使用例:

こんな関数を*scratch*バッファで定義(関数定義の直後でC-j)する。ファイル名をHelloして、テキストを大文字化するという無意味なもの。

(defun hello (file)
  (interactive "f")
  (find-file file)
  (message "Hello, %s!" file)
  (upcase-region (point-min) (point-max))
  (save-buffer)
  (kill-buffer))

diredで適当なファイルをマーク(複数可)してM-x dired-M-x RET hello RETとするとエコーエリアにHello, FILENAME!と表示されマークされたファイルは大文字化される。

find-file, save-buffer, kill-bufferは定型なのでマクロを書いておけば便利:

(defmacro with-find-file (file &rest body)
  `(progn (find-file ,file)
          (progn ,@body)
          (save-buffer)
          (kill-buffer)))

そうすると上の例は次のようになる(この例だとそれほど有難味はない):

(defun hello (file)
  (interactive "f")
  (with-find-file
   file
   (message "Hello, %s!" file)
   (upcase-region (point-min) (point-max))))

dired-M-xは適当なキーにバインドしておくと良いので、たとえば

(define-key dired-mode-map (kbd "X") 'dired-M-x)

とする。&(dired-do-async-shell-command)があるので!(dired-do-shell-command)を上書きしてしまってもいいかも知れない。