Rename multiple files at the same time

Renaming files using mmv:

$ mmv '???-*' '#4'
       ^^^ ^    ^
       123 4    4

You could also match digits with range match:

$ mmv '[0-9][0-9][0-9]-*.txt' '#4.txt'
         ^    ^    ^   ^        ^
         1    2    3   4        4

(recursively rename files):

$ mmv ';???-*' '#1#5'
       ^^^^ ^    ^ ^
       1234 5    1 5
  • ; Expands to any number of directories (same as **/).
  • * Matches any char zero or more times.
  • ? Matches any single character.
  • [] Matches a list or and a range of characters.
  • # References to the nth wildcard char in the from pattern.

With Perl-based rename command:

$ rename -n 's/\d{3}-//' [0-9][0-9][0-9]-*.txt
rename(000-hello.txt, hello.txt)
rename(001-world.txt, world.txt)
rename(002-ubuntu.txt, ubuntu.txt)
rename(003-linux.txt, linux.txt)

If the number of files is large enough to make the command exceed the shell's ARG_MAX, then you could use either

printf '%s\0' [0-9][0-9][0-9]-*.txt | xargs -0 rename -n 's/\d{3}-//'

or

find . -maxdepth 1 -name '[0-9][0-9][0-9]-*.txt' -exec rename -n 's/\d{3}-//' {} +

Note that [0-9][0-9][0-9]-*.txt is processed by the shell and needs to be a shell glob expression rather than a regular expression.

Remove the -n once you are happy that it is doing the right thing.


Since I don't see it mentioned here yet, you can use repren. While it isn't installed by default, it does support regular expression-based file renaming. You can do just a single regular expression pattern like so:

repren --rename --from "^[0-9]{3}" --to "" --dry-run .

The above example deletes the first 3 digits in all filenames if they are at the beginning thereof for all files recursively in the current directory. It does a dry run though to show you what it will do without actually doing it - remove the --dry-run bit once you're sure that it will do what you intend.

repren also supports pattern files, allowing you to do multiple replacements in 1 go:

repren --rename --patterns=path/to/patternfile

A pattern file looks like this:

regex_1<tab_character>replacement_1
regex_2<tab_character>replacement_2

...and so on.

Finally, it supports regular expression groups. Consider this pattern file:

# This is a comment
figure ([0-9+])<tab>Figure \1

The \1 syntax inserts the contents of the first (bracketed) group. To do this on the command-line, you'd need to use single quotes I think (correct me if I'm wrong):

repren --rename --from 'figure ([0-9+])' --to 'Figure \1' --dry-run path/to/directory_or_files_here

This is just scratching the surface of what repren is capable of though. It can optionally alter the contents of files too (hence the need for --rename in all the above examples).

Disclaimer: I am not affiliated with repren or it's development in any way, I just find it an invaluable time-saving tool.