To quickly rename a bunch of files, use rename
.1
For example, here’s how you’d lowercase everything in the current folder:
rename --force --lower-case *
rename
is especially useful for things like changing case, adding and removing strings, or finding and replacing patterns in filenames.
Here are some more examples showing how it works:
- Targeting Files
- Changing Case
- Adding Strings
- Removing Strings
- Finding and Replacing Strings
- Regular Expressions
- Combining Transforms
- URL-Friendly Filenames
- Numbering Files
- Testing
- Options & Abbreviations
- How to Install
To get started now, skip to How to Install. For additional resources, see References.
Targeting Files
You can select files with glob patterns.
rename [options] *
: Rename all files in the current folder.rename [options] *.jpg
: Rename all.jpg
files in the current folder.rename [options] **/*.jpg
: Rename all.jpg
files in this folder and all subfolders.
I’ll use *.jpg
in the rest of my examples, but know you can replace that with any glob pattern to match your own files.
P.S. You can also pass multiple patterns, so the following examples will also work.
rename [options] *.jpg *.jpeg
rename [options] folder1/*.jpg folder2/*.jpg
rename [options] file1.jpg file2.jpg file3.jpg
Changing Case
Use --lower-case
, --upper-case
, and --camelcase
to change the case of all matching files.
rename --force --keep-extension --upper-case *.jpg
--force
: macOS and other systems are case-insensitive by default, meaning they think “FILE.jpg” and “file.jpg” are the same filename. Unless you force it,rename
will not change those filenames because the file “already exists.”--keep-extension
: By default, changes apply to the entire filename—including the file extension. If you don’t want to accidentally change your file extensions, add this option to the beginning of your command. (Sincerename
applies its options sequentially, if you add the option too late then your transforms will apply first—before “keep” can take effect.)
Adding Strings
Use --prepend
or --append
to add strings to the beginning or end of all matching files.
rename --prepend 'example-' *.jpg
This adds “example-” to the beginning of all the text files in the current folder.
Removing Strings
Use --delete
or --delete-all
to remove strings from all matching files.
rename --delete 'example-' *.jpg
This removes “example-” from all the text files in the current folder.
Note: --delete
only removes the first match from a filename. If the string you’re trying to remove shows up more than once in a filename (e.g., example-example-file.jpg
) and you want to remove all matches, use --delete-all
instead.
Finding and Replacing Strings
Use --subst
or --subst-all
to change “find” to “replace” in all the text files in the current folder.
rename --subst-all 'find' 'replace' *.jpg
Note: Like --delete
, if you only want to substitute the first match in a filename then you can just use --subst
. Personally, I use --subst-all
more often.
Regular Expressions
Now it gets real: the full power of regular expressions in a handy renaming tool.
rename --expr 's/find/replace/g' *.jpg
You can literally do all the other examples we’ve covered with just the --expr
option—it’s that powerful.
- Changing Case:
rename --expr 's/([A-Z])/\l$1/g' *.jpg
2 - Adding Strings:
rename --expr 's/^/prepend-/' *.jpg
3 - Removing Strings:
rename --expr 's/delete//' *.jpg
4
Bonus: The --expr
option is implied for the first expression, so you can simply pass your regex argument and it will still work.
rename 's/find/replace/g' *.jpg
Combining Transforms
rename
’s options are applied sequentially, which means it applies each option one at a time in order. (This is especially important for options like --keep-extension
.)
That means you can apply multiple transforms in a single command.
URL-Friendly Filenames
Here’s how you can combine multiple transforms to make all your filenames URL-friendly (i.e., lowercase with dashes).
rename --force --lower-case --sanitize --subst-all '_' '-' *.jpg
--force
: Force filename changes, even if my operating system thinks they’re the same.--lower-case
: Lowercase the whole filename.--sanitize
: Replace all whitespace, control characters, and meta-characters with underscores.--subst-all '_' '-'
: Change all underscores to dashes.*.jpg
: Rename all.jpg
files in the current folder.
Numbering Files
Bonus round! rename
also includes a built-in counter, so you can easily number (or renumber) all your files.
rename --keep-extension --expr 's/^\d+//' --counter-format 001 --expr 's/$/-$N/' *.jpg
This replaces prefixed numbers in the filename with a zero-padded suffix (e.g., changing 1-file.jpg
to file-001.jpg
).5
--keep-extension
: Don’t apply changes to the file extension.--expr 's/^\d+-//'
: Use regex to replace any numbers (\d+
) followed by a dash(-
) at the beginning of the filename (^
) with an empty string.--counter-format 001
: Format the counter with padded zeroes, and start counting at 1. This sets the value for$N
in the next expression, and will output001
,002
, etc. (If you want, you can also start counting at 0 with000
, or just about any other number.)--expr 's/$/-$N/'
: Use regex to append a dash (-
) and the current counter value ($N
) at the end of the filename ($
).*.jpg
: Rename all.jpg
files in the current folder.
Testing
With so much power, it’s easy to make mistakes. That’s why rename
has a --dry-run
option. Add this to show what files would be renamed without actually changing anything.
rename --dry-run --verbose [options] *.jpg
--dry-run
: Don’t actually make any changes. Just show me what would happen.--verbose
: Log everything that happens when I run the command.
(I’d recommend always including --verbose
, or its abbreviation -v
.)
Options & Abbreviations
For all you power users out there, there are abbreviations for almost every option, so you can trim longer commands down to snippets like rename -cf *
(lowercase everything).
Here’s a quick list of all the options we’ve used in this post:
Switches
-f
/--force
: Force filename changes, even if my operating system thinks they’re the same.-n
/--just-print
/--dry-run
: Don’t actually make any changes. Just show me what would happen.-N
/--counter-format
: Format and set the$N
counter variable.-v
/--verbose
: Log everything that happens when I run the command.
Transforms
-a
/--append
: Add text to the end of the filename.-A
/--prepend
: Add text to the beginning of the filename.-c
/--lower-case
: Lowercase the filename.-C
/--upper-case
: Uppercase the filename.-d
/--delete
: Delete the first match in a filename.-D
/--delete-all
: Delete all the matches in a filename.-e
/--expr
: Apply a Perl expression to the filename (e.g., a regex).-s
/--subst
: Substitute the first match in a filename.-S
/--subst-all
: Substitute all the matches in a filename.-X
/--keep-extension
: Don’t apply changes to the file extension.-z
/--sanitize
: Replace all whitespace, control characters, and meta-characters in the filename with underscores.
To see a full list of options & abbreviations, just run rename
without any options in your terminal to view the “Usage” docs.
And that’s it for today!
How to Install
Use Homebrew to install rename
on macOS.
brew install rename
For other operating systems, try searching for “linux rename install”.
References
The best way to learn more about rename
is to check out its manual in your terminal.
rename --man
Beyond that, there’s a couple of dense Linux & Perl docs, a handful of good blog posts, and several scattered Stack Overflow answers to learn more from.
-
Each of these examples deserves some more explaining, so here’s a quick breakdown of how the “Changing Case” expression works:
rename --expr 's/([A-Z])/\l$1/g' *.jpg
s/…/…/
is a Perl expression. Thes
is a “substition operator.” It substitutes the match from the first part of the expression (between the first two slashes) with the content in the second part of the expression (between the last two slashes).- There’s also
tr
, the “transliteration operator” (akay
), which is probably the only other operator you’d use withrename
. It can simplify some expressions (e.g., lowercase would just bey/A-Z/a-z/
), but most of the times
should be all you need. For more details on Perl expressions, check out Perl Doc: Quote-Like Operators and Perl Doc: Regexp Quote-Like Operators.
- There’s also
([A-Z])
matches all the uppercase characters and captures them in a “group” that we can access later with a “match variable” (that’s the$1
part towards the end).- Parentheses are important! If you leave them out, you’ll get an error: “Use of uninitialized value $1 in substitution.” That’s because
$1
is only set after you capture a pattern. To fix, simply add those parens()
around your pattern. For a deeper dive, see Perl Doc: Perl regular expressions – Capture groups.
- Parentheses are important! If you leave them out, you’ll get an error: “Use of uninitialized value $1 in substitution.” That’s because
\l
lowercases the next character after it, which in this case is our match group,$1
. In other words, it lowercases each uppercase character we find.g
at the end is a “global matching” modifier, which says to replace every match in the string, not just the first one we find. For more details on theg
flag and other regex modifiers, check out Regular-Expressions.info: Perl Text Patterns for Search and Replace and Perl Doc: Using regular expressions in Perl – Global matching.
-
You can also append text using the
$
anchor instead of^
:rename --expr 's/$/-append/' *.jpg
. For more details on anchors, check out Regular-Expressions.info: Start and End of String or Line Anchors. ↩ -
This little regex simply says “replace the string ‘delete’ with nothing.” See note #2 above for more details on the “substition operator.” ↩
-
If you just want to number your files, you can simplify this command:
rename --keep-extension --expr 's/$/-$N/' *.jpg
. Or if you want to replace the entire filename:rename 's/.*/$N.jpg/' *.jpg
. ↩