Andrew Mercer
on this page

rename (util-linux)

rename replaces a fixed string in one or more file names. It's the quickest way to bulk-rename files without writing a loop.

Which rename do you have? There are two unrelated tools with the same name:

Variant Syntax Found on
util-linux rename rename FROM TO FILES... (plain strings) RHEL, Fedora, Arch, Alpine; rename.ul on Debian/Ubuntu
Perl rename (prename, file-rename) rename 's/regex/repl/' FILES... Default rename on Debian/Ubuntu

Check with rename --version. util-linux prints rename from util-linux 2.x. This page covers the util-linux version.

Syntax

rename [options] <expression> <replacement> <file>...
  • expression — literal string to find (not a regex)
  • replacement — string to put in its place (can be empty '' to delete)
  • file... — usually a shell glob

By default only the first occurrence in each name is replaced.

Options

Option Description
-n, --no-act Dry run; show what would happen (pair with -v)
-v, --verbose Print each rename performed
-o, --no-overwrite Don't clobber existing files
-i, --interactive Prompt before overwriting
-a, --all Replace every occurrence, not just the first
-l, --last Replace the last occurrence instead of the first
-s, --symlink Rewrite the target of symlinks rather than the link names

-a and -l were added in util-linux 2.38; older systems (e.g. RHEL 8/9) won't have them.

Always dry-run first

rename -nv .jpeg .jpg *.jpeg
`photo1.jpeg' -> `photo1.jpg'
`photo2.jpeg' -> `photo2.jpg'

Drop -n once the output looks right.

Common examples

Change an extension

rename -v .jpeg .jpg *.jpeg

Strip a prefix

rename -v 'IMG_' '' IMG_*.jpg

Add a prefix (you can't match "nothing", so match a known leading string and include it in the replacement)

rename -v 'report' '2026-report' report*.pdf

Replace all spaces with underscores (needs -a)

rename -av ' ' '_' *

On older util-linux without -a, run it repeatedly until nothing changes:

while rename ' ' '_' *\ * 2>/dev/null; do :; done

Change only the last occurrence (handy for extensions on names with dots)

rename -lv '.bak' '' config.bak.bak
# config.bak.bak -> config.bak

Zero-pad numbered files (one pass per digit length)

rename -v 'file' 'file0' file?.txt     # file1.txt -> file01.txt

Avoid clobbering existing files

rename -ov .log .txt *.log

Retarget symlinks after moving a directory

rename -sv /opt/app-old /opt/app-new /etc/alternatives/app*

Recursive rename (rename has no -r; combine with find)

find . -type f -name '*.jpeg' -exec rename -v .jpeg .jpg {} +

Directories renamed while find is walking them can break traversal — use -depth when renaming directory names:

find . -depth -name '*old*' -exec rename -v old new {} +

Exit status

Code Meaning
0 All requested renames succeeded
1 All renames failed
2 Some renames failed
4 Nothing was renamed (expression not found)
64 Unanticipated error

Useful in scripts — 4 tells you the pattern matched nothing.

Gotchas

  • Not a regex. rename '.*' ... looks for a literal .*. Use the Perl rename or a shell loop for patterns.
  • Matches the whole path. rename a b dir/a.txt changes the first a in dir/a.txt — fine here, but rename d x data/d.txt hits the directory part. cd into the directory or make the expression specific.
  • Quote spaces and empty strings. '' for an empty replacement, ' ' for a space.
  • Debian/Ubuntu: install util-linux (already present) and call rename.ul, or install the rename package for the Perl variant.

Shell-only alternative

When rename isn't available or you need logic it can't express:

for f in *.jpeg; do mv -n -- "$f" "${f%.jpeg}.jpg"; done

See also

  • man 1 rename
  • mmv, mv, Perl rename (file-rename)