1

Having a remote directory open in Emacs (... via TRAMP), I can run remote commands on remote files (using !). I can also view them locally (... even if they're image files) with builtin Emacs viewers (just "Enter"), resulting in the file being copied over to the local disk transparently.

Is there a way to run a non-Emacs command that's only available on the local machine (... on which Emacs is running; e.g. an X11 pdf viewer), with the input being the remote file, in a way that's simpler than copying over the remote file manually first?

  • I don't know of a default command for that, although you could write one by binding default-directory to a local path before calling shell-command. However, given that you would need to specify the remote file path using a non-tramp syntax -- and what that syntax was (if it existed at all) would be dependent on the command you were running -- it doesn't seem to me like an obvious thing to try to do. – phils Jun 26 '18 at 2:01
  • You could, however, have an Emacs command which copied the remote file to a local temporary file, and invoked the local shell command on the local temporary file. file-local-copy is a function which does the copy-to-a-local-temp-file part of that approach. – phils Jun 26 '18 at 2:01
3

I've written the following snippet which (as far as I can tell) does what you're looking for from the point of view of the ! command.

It does the following:

  • Takes the files that would have operated on by dired-do-shell-command (i.e. the ! key). This will be either the marked files, the file under point if nothing is marked or the files specified by a prefix arg. As far as I can tell this is the same as the behavior you get from !
  • Downloads a local (temporary) copy of each of the files in directory specified by temporary-file-directory on your system.
  • Runs dired-do-shell-command in that directory on that file or files
(defun dired-do-local-command ()
  (interactive)
  (let* ((marked-files (dired-get-marked-files nil current-prefix-arg))
         (local-tmp-files (mapcar #'file-local-copy marked-files))
         (num-files (length local-tmp-files))
         (default-directory temporary-file-directory)
         (command (dired-read-shell-command "! on %s: " num-files marked-files)))
    (dired-do-shell-command command num-files local-tmp-files)))

You can bind this to a key in dired mode (I've chosen ") with

(define-key dired-mode-map (kbd "\"") 'dired-do-local-command)

and it should behave similarly to the ! key.

  • Many thanks to @phils for pointing me in the right direction. – Mark Nov 6 at 12:21
  • It looks like (mapcar (lambda (marked-filename) (file-local-copy marked-filename)) marked-files) could be (mapcar #'file-local-copy marked-files) ? – phils Nov 6 at 23:19
  • Nice to see the implementation, btw. Have upvoted :) – phils Nov 6 at 23:22
  • file-local-copy & a solution like this sounds perfect, thanks!!! – Latanius Nov 7 at 21:25
  • Updated the answer to reflect suggestions from @phils. Thanks for pointing that out. – Mark Nov 8 at 22:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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