3

I have the following files in a directory:

CIMG4879.JPG
CIMG4880.JPG
CIMG4881.JPG
...

I want to rename them all with a numeric sequence such that:

01.jpg
02.jpg
03.jpg
...

In bash, I could convert *.JPG %02d.jpg, since they're all image files.

How do I do a batch rename in dired? Assume I have a lot a files, so doing it one by one would be tedious and error-prone.

2
  • One option would be to use shell commands in a dired-mode buffer by typing the exclamation point keyboard shortcut: ! You may wish to mark one or more files ahead of time.
    – lawlist
    Oct 1, 2016 at 18:58
  • 1
    I did not know convert could rename files this way (actually it does create new files with the intended names). I'm not sure what converting a jpg to a jpg means, especially since the sizes of input and output files differ...
    – JeanPierre
    Oct 1, 2016 at 20:59

3 Answers 3

10

Firstly, take note of JeanPierre's comment -- you're not renaming files by using convert like that. You're creating new and different files (lower quality ones, although the difference may or may not matter in practice, depending on your use-cases).

Here are a few different options for renaming files in dired using a number sequence. The first two are general techniques for editing text, which are applicable thanks to the excellent wdired-mode. The third combines dired's rename command with keyboard macro counters.

  1. With search-and-replace:

    • C-xC-q (change to editable dired mode; use C-c C-k to cancel the edit if you mess anything up)
    • C-M-% (call query-replace-regexp)
    • CIMG[0-9]+\.JPG (pattern to match)
    • \,(format "%02d" (1+ \#)).JPG (replacement)
    • ! (replace all; or else you could confirm the replacements individually)
    • C-cC-c (to return to normal dired mode, writing the changes)

\,(...) calls an elisp function and uses the result in the replacement text; here we are calling format on the replacement counter, to which we are first adding one (as it counts from zero).

(It's a shame that dired-do-rename-regexp doesn't support that, but not a big deal when you're familiar with wdired-mode.)

  1. Once again in editable dired mode, mark the filenames as a rectangle, delete the rectangle, then use rectangle-number-lines to insert new contents:

    • C-uC-xrN call rectangle-number-lines with extended argument input
    • Start from 1
    • Use %02d as the replacement, being sure to remove the default trailing space (or you could use %02d.JPG, depending on what you actually deleted)
  2. With keyboard macros, in normal dired:

    • C-xC-kC-f %02d (set kmacro counter format)
    • M-1F3 (start recording, initialising counter to 1)
    • R (dired rename)
    • F3 (insert the current kmacro counter value; the counter then increments)
    • .JPG RET (remainder of the new filename)
    • C-n (next line)
    • F4 (repeatedly; first to end recording, and then to repeat the macro)

You can use M-0F4 to repeat the macro as many times as possible.

5
  • Great answer. It would be even greater with some pointers on the relevant docs! (since it's the kind of answer that makes one feel one should learn more about that).
    – JeanPierre
    Oct 2, 2016 at 11:53
  • I filed Emacs bug (enhancement request) #24587 , to enable dired-do-rename-regexp to fully support query-replace-regexp replacement-pattern syntax.
    – Drew
    Oct 2, 2016 at 16:52
  • JeanPierre: Documentation: Type C-h r for the manual, g to enter an info node by name, and then Regexp Replace or Rectangles or Keyboard Macros.
    – phils
    Oct 2, 2016 at 20:24
  • @phils with this \,(format "%02d" (1+ \#)).JPG, is there anyway I can make it start from 40 instead of 0?
    – reFORtEM
    Mar 31, 2019 at 15:29
  • 1
    @William Yes indeed -- simply change (1+ \#) to (+ 40 \#). See C-h f + and C-h f 1+ regarding the slightly different syntax (they're both elisp functions).
    – phils
    Mar 31, 2019 at 21:07
2

In dired I do not know the regexp

Why bother with dired's regex-replacement? Just enter wdired-mode (which I bind to w in dired, but default=C-x C-q), edit the filenames like regular text, then exit back to normal dired with C-c C-c.

1
(defun rename-files-numeric-sequence ()
  (interactive)
  (let ((sequence 1)
        (files (directory-files-recursively default-directory "")))
    (while files
      (rename-file (car files)
                   (format "%s%03d.%s"
                           (file-name-directory (car files))
                           sequence
                           (file-name-extension (car files))))
      (setq files (cdr files))
      (setq sequence (1+ sequence)))))
1
  • Good initiative. But this answer seems independent of Dired. Maybe you'd like to add a Dired command that invokes such code but acts, e.g., on the marked files?
    – Drew
    Mar 24, 2021 at 2:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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