Emacs: Move Image File 🚀

By Xah Lee. Date: . Last updated: .

Here's a emacs command that moves image file from download directory to your blog directory and create a html image link to it.

You can customize which directories to search, and a list of regex to match the file you want to move.

This command is useful if you write a blog and often want to include screenshots or photos you have taken, or images from internet.

put this in your Emacs Init File:

(defvar xah-html-move-image-file-from-dirs nil
  "A list of dir paths used by `xah-html-move-image-file' to search for image files to move from.
Each should be full path, and end in a slash.
Version 2023-07-01.")
(setq
 xah-html-move-image-file-from-dirs
 (mapcar
  (lambda (x)
    (expand-file-name (file-name-as-directory x)))
  '(
    "~/Downloads/"
    "~/Videos/Captures/"
    "~/Pictures/Screenshots/"
    "~/Pictures/"
    "~/Desktop/"
    "~/"
    "/tmp/"
    )))

(defvar xah-html-move-image-file-target-dir nil
  "A string for path, used by `xah-html-move-image-file' to move file to target dir.
Path should be a relative path.
It is used relative to current dir when the command is called.
(If this string is empty, it means the current dir.)
If the dir do not exist, it is created.
Version 2023-07-01")
(setq xah-html-move-image-file-target-dir "i" )

(defvar xah-html-move-image-file-regex-list nil
  "A list of regex strings used by `xah-html-move-image-file' to search for temp image files.")
(setq
 xah-html-move-image-file-regex-list
 '(
   "^tt"
   "^ee"
   "unknown\\.jpg"
   "unknown\\.png"
   "image\\.png"
   "^[A-Za-z0-9]\\{15\\}\\.\\(png\\|jpg\\)$"

   "^IMG.+?\\.\\(png\\|jpg\\)$"
   "^IMG_.+?\\.\\(png\\|jpg\\)$"
   "^DSC_.+?\\.\\(png\\|jpg\\)$"
   "^capture.*?\\.\\(png\\|jpg\\)$"
   "^Screen Shot.+?\\.\\(png\\|jpg\\)$"
   "^Screenshot.+?\\.\\(png\\|jpg\\)$"
   "^screenshot.+?\\.\\(png\\|jpg\\)$"

   " PM\\.\\(png\\|jpg\\)$"
   " AM\\.\\(png\\|jpg\\)$"

   ;; amazon pic
   ;; 718XHsTfXcL.__AC_SX300_SY300_QL70_FMwebp_.webp
   ;; 61-UjxyNjgL._AC_SL1500_.jpg
   ;; 81IVDfmw4KL._AC_SL1500_.jpg
   "[-+0-9A-Za-z]\\{11\\}\._+[A-Z]\\{2\\}.+\.\\(jpg\\|webp\\)"
   ;; "[+0-9A-Za-z]\\{11\\}\._+[A-Z]\\{2\\}_[A-Z].+\.\\(jpg\\|webp\\)"
   ))

(defun xah-html-move-image-file ()
  "Move a image file from source to target dir, and maybe create a image link.

The source dirs to search is defined in `xah-html-move-image-file-from-dirs'.

The file names pattern to search is defined in `xah-html-move-image-file-regex-list'.
First match is acted on.

The target dir is defined by `xah-html-move-image-file-target-dir'.
If the target dir does not exist, it is created.

A random string is added to file name (as id), and any uppercase file extension name is lowercased, example: .JPG becomes .jpg. Space in filename is replaced by the lowline char _.
if it already exist

The final source path and target path is printed to the messages buffer.

If current buffer is a file running `xah-html-mode', also insert a embed image tag.

Automatically call `xah-dired-remove-all-metadata' and `xah-dired-optimize-png' afterwards.

URL `http://xahlee.info/emacs/emacs/move_image_file.html'
Version: 2019-01-11 2023-01-26 2023-07-01"
  (interactive)
  (let ((xm0 (make-marker)) xfromPath xext xnewName xtoDir xtoPath)
    (set-marker xm0 (point))
    (setq xfromPath
          (catch 'found57804
            (dolist (xdir xah-html-move-image-file-from-dirs)
              (when (file-exists-p xdir)
                (let ((xdirFiles (directory-files xdir t (mapconcat 'identity xah-html-move-image-file-regex-list "\\|"))))
                  (when xdirFiles (throw 'found57804 (car xdirFiles))))))))
    (when (not xfromPath) (error "%s: No file name matched regexes `xah-html-move-image-file-regex-list' at dirs `xah-html-move-image-file-from-dirs'" real-this-command))
    (setq xext
          (let ((xx (file-name-extension xfromPath)))
            (if xx
                (if (seq-some (lambda (xy) (string-equal xy xx)) '("jpg-large" "jpg_large" "jpg_medium" "jpeg" "jfif"))
                    "jpg"
                  (downcase xx))
              "")))
    (setq
     xnewName
     (with-temp-buffer
       (insert (file-name-nondirectory (file-name-sans-extension xfromPath)))
       (progn
         (goto-char (point-min))
         (when (re-search-forward "^tt[0-9]*" nil t) (replace-match "")))
       (progn
         (goto-char (point-min))
         (when (search-forward "Screen Shot" nil t) (replace-match "ssht")))
       (progn
         (goto-char (point-min))
         (when (search-forward "screenshot" nil t) (replace-match "ssht")))
       (progn
         (goto-char (point-min))
         (while (re-search-forward "[, +|]" nil t)
           (replace-match "_")))
       (goto-char (point-max))
       (insert "_")
       (let ((xcharset "bcdfghjkmnpqrstvwxyz23456789BCDFGHJKMNPQRSTVWXYZ") xlen)
         (setq xlen (length xcharset))
         (dotimes (_ 4)
           (insert (aref xcharset (random xlen)))))
       (buffer-string)))
    (setq xtoDir
          (file-name-as-directory
           (expand-file-name
            (file-name-concat default-directory xah-html-move-image-file-target-dir))))
    (if (file-exists-p xtoDir)
        nil
      (make-directory xtoDir))
    (setq xtoPath (concat xtoDir xnewName "." xext))
    (if (file-exists-p xtoPath)
        (error "Target path exist: %s" xtoPath)
      (progn
        (print (format "%s: file moved from\n%s\nto\n%s"
                       real-this-command
                       xfromPath xtoPath))
        (rename-file xfromPath xtoPath)
        (when (string-equal major-mode "dired-mode")
          (revert-buffer))
        (if (string-equal major-mode "xah-html-mode")
            (progn
              (kill-new xtoPath)
              (goto-char xm0)
              (insert "\n\n"  xtoPath "\n\n")
              (backward-word)
              (xah-html-any-to-link))
          (progn
            (goto-char xm0)
            (insert "\n\n" xtoPath "\n\n")))
        (when (fboundp 'xah-dired-remove-all-metadata)
          (xah-dired-remove-all-metadata (list xtoPath) t))
        (when (and (string-equal xext "png") (fboundp 'xah-dired-optimize-png))
          (xah-dired-optimize-png (list xtoPath)))))))

you probably also want to install Emacs: Xah Dired Mode (xah-dired.el)