26

Does elisp have a function that takes a url and a destination and downloads that url off the internet?

I've discovered url-retrieve and url-retrieve-synchronously but url-retrieve takes a callback and url-retrieve-synchronously puts everything into a buffer. Is there anything simpler?

Cristian
  • 42,563
  • 25
  • 88
  • 99
  • 1
    If you just want to get the remote file into an Emacs buffer, `browse-url-emacs` is handy. – phils Jul 03 '12 at 22:45

4 Answers4

33

Try url-copy-file. Its description reads,

url-copy-file is an autoloaded Lisp function in `url-handlers.el'.

(url-copy-file url newname &optional ok-if-already-exists keep-time)

Copy url to newname. Both args must be strings. Signals a `file-already-exists' error if file newname already exists, unless a third argument ok-if-already-exists is supplied and non-nil. A number as third arg means request confirmation if newname already exists. This is what happens in interactive use with M-x. Fourth arg keep-time non-nil means give the new file the same last-modified time as the old one. (This works on only some systems.) A prefix arg makes keep-time non-nil.

huaiyuan
  • 26,129
  • 5
  • 57
  • 63
  • I had to ```require 'url``` to use ```url-copy-file``` – Nate Sep 04 '17 at 01:25
  • 3
    (For Emacs newbies) If you want to use this like `wget` (i.e. not as a part of a program or function) you can type `ESC :` (which prompts for an elisp expression to eval) then type: `(url-copy-file "http://example.com/" "filename.txt")` – Ashton Wiersdorf Nov 17 '17 at 22:11
12

Obviously url-copy-file is the best option, but to the more adventurous Emacs hackers I'd suggest something like this:

(require 'url)

(defun download-file (&optional url download-dir download-name)
  (interactive)
  (let ((url (or url
                 (read-string "Enter download URL: "))))
    (let ((download-buffer (url-retrieve-synchronously url)))
      (save-excursion
        (set-buffer download-buffer)
        ;; we may have to trim the http response
        (goto-char (point-min))
        (re-search-forward "^$" nil 'move)
        (forward-char)
        (delete-region (point-min) (point))
        (write-file (concat (or download-dir
                                "~/downloads/")
                            (or download-name
                                (car (last (split-string url "/" t))))))))))
Bozhidar Batsov
  • 55,802
  • 13
  • 100
  • 117
  • This seems like the way to go for a custom download path. I tried url-copy-file but couldn't get it to work on Windows since it was using the emacs directory concatenated with whatever download name I gave it. With this code it downloads to any given folder, no problem. Extremely useful on a windows machine with no programming environments installed except emacs, heh. – Darren Ringer May 13 '22 at 04:48
4

http://steloflute.tistory.com/entry/Emacs-Lisp-urlretrieve

; synchronously    
(defun get-url (url)
  (with-current-buffer (url-retrieve-synchronously url) (buffer-string)))

(print (get-url "http://www.gnu.org"))

; asynchronously    
(defun print-url (url)
  (url-retrieve url (lambda (a) (print a))))

(print-url "http://www.gnu.org")

Retrieving URLs | http://www.gnu.org/software/emacs/manual/html_node/url/Retrieving-URLs.html

Current Buffer | http://www.gnu.org/software/emacs/manual/html_node/elisp/Current-Buffer.html

KIM Taegyoon
  • 1,917
  • 21
  • 18
4
(w3m-download "http://www.gnu.org/index.html")
viam0Zah
  • 25,949
  • 8
  • 77
  • 100