How to rename files to specific string in their filenames

I have large amount of .json files that need to be renamed to a specific string of numbers in each file’s name. They follow the format:

[Artist] Title (Date) [Language][Publisher][Website.####][Pages].json

"####" represents a unique numerical ID which I need to rename each file to, ranging from 1-4 characters long. It should look like this:


How can I achieve this?

Asked By: fukaeri


With zsh:

autoload -Uz zmv
zmv -n '*[*.(<->)][*(.json)' '$1$2'

Remove the -n (dry-run) if happy.

The zmv autoloadable function takes two arguments:

  1. a zsh extended glob pattern
  2. a replacement specification

It finds the files that match the pattern, here all the non-hidden ones in the current directory that contain in sequence:

  • * any number of characters (or bytes)
  • [ a literal [
  • * any number of characters (or bytes)
  • . a literal .
  • <-> any sequence of ASCII decimal digit (<x-y> matches on sequences of ASCII decimal digits representing numbers from x to y)
  • ][: ][ literally.
  • * any number of characters (or bytes)
  • .json: literally.

In the replacement, $1 expands to what was matched inside the first pair of (...), so the number matched by <-> and $2 to the second (.json).

Note that as those * match greedly, it will find that number in the rightmost pair of [...] whose contents ends in .<digits> (excluding the last). For instance in [a.1][a.2.3][x][y][z].json, it will extract 3 even though that’s not in the second-last pair of [...]s.

If that’s a problem, you can change it to:

zmv -n '*.(<->)][[^][]#](.json)' '$1$2'

Where [^][]# matches on 0 or more characters (or non-characters) other than [ and ].

Answered By: Stéphane Chazelas
Categories: Answers Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.