I have a directory full of images:

image0001.png
image0002.png
image0003.png
...

And I would like a one-liner to rename them to (say).

0001.png
0002.png
0003.png
...

How do I do this?

  • 7
    This is one of the top Unix command line FAQs, and I can't find it on this site already, so should we make this Community Wiki? – Gilles Aug 24 '10 at 0:08
  • 5
    I don't see why. It's a specific question with a verifiable answer. – Internet man Aug 24 '10 at 0:45
  • 3
    If you're running X it doesn't get much easier than thunar -B *.png for thunar's bulk-rename gui tool. – dotjoe Aug 25 '10 at 21:26
  • @dotjoe Thanks, Thunar is interesting indeed. – Volker Siegel Oct 9 '14 at 3:20

14 Answers 14

up vote 85 down vote accepted

If you are using bash:

for f in *.png; do mv "$f" "${f#image}"; done
  • 2
    This is one of the parameter substitution methods shown in Mendel Coopers Advanced Bash-scripting guide tldp.org/LDP/abs/html – W_Whalley Aug 25 '10 at 14:15
  • 1
    @W_Whalley I strongly recommend avoiding that guide, in favor of the Wooledge Bash Guide. – Wildcard Nov 27 '16 at 17:55
  • @Wildcard: what are your reasons for recommending to avoid the ABS guide? – Christian Severin Oct 11 '17 at 11:27
  • @ChristianSeverin promotion of bad practices and outright broken code. Check links on my profile page. – Wildcard Oct 11 '17 at 16:20

On Debian and derivatives, Perl's rename works similarly to sed like this:

  rename -v 's/image//' *.png

There's also the rename from util-linux that works like this, instead:

  rename image '' *.png
  • 5
    you really should explain that this is a perl programm that might have to be installed and that it takes regular expressions as the argument. – user601 Aug 24 '10 at 0:30
  • Ah, I was not aware of that. I'll give credit to the canonical answer, when I identify it :) – Internet man Aug 24 '10 at 0:33
  • 5
    This rename program came from a Perl examples distribution. Debian and Ubuntu ship it as /usr/bin/rename. Other Unix variants may not provide it, or may provide a completely different /usr/bin/rename. – Gilles Aug 24 '10 at 7:17
  • 1
    Some versions of rename take a from to replacement pattern: rename [options] <expression> <replacement> <file>... – melds Dec 29 '15 at 18:42
  • 1
    If you are using a Debian based system then sudo apt-get install rename, then you can use the rename command. It is sed for filenames. – ctrl-alt-delor Dec 31 '16 at 17:20

zmv

The zsh shell has a powerful batch rename command called zmv.

First you need to enable the zmv command as follows (this can go into your ~/.zshrc).

autoload zmv

The basic syntax is zmv PATTERN REPLACEMENT. The pattern is a shell glob expression. Parts of the pattern can be surrounded by parentheses. The replacement text can contain $1, $2, etc. to refer to the Nth parenthesised group in the pattern. For example:

zmv 'image(*.png)' '$1'

You can also ask zsh to automatically define $1, $2, etc. to match the wildcard characters in the pattern:

zmv -w 'image*.png' '$1.png'
  • 4
    sweeeeeeeeeeeeeeeeeet. yet another reason i should be learning zsh. – ixtmixilix Oct 11 '11 at 13:16
  • 1
    @ixtmixilix what's to learn? Just start using it and perhaps add prezto (github.com/sorin-ionescu/prezto) for some extra awesomeness. – Gerry Aug 15 '12 at 8:09
  • Really cool, as pointed in zmv's man this can be further simplified by adding alias mmv='noglob zmv -W' to: mmv *.c.orig orig/*.c – Bretsko Aug 29 '17 at 16:10

I normally use the nice and simple mmv (man page) utility for this usecase:

$ mmv "image*.png" "#1.png"

will perform your task.

The #1 in the target pattern will be substituted with whatever matches the wildcard in the source pattern. This also works for several wildcards and can be used for example to change the order of parts of filenames. You can also easily do more complicated things like converting lower case to upper case letters.

Make sure to protect the patterns from the shell by quoting.

  • Thanks for pointing out this utility. I found it in Debian, Ubuntu and Cygwin repositories. I had trouble with the man page, but found some web pages and this Stack Overflow question that helped explain how you were using it. stackoverflow.com/questions/417916/how-to-do-a-mass-rename – W_Whalley Aug 25 '10 at 16:12
  • Thanks, I added some more information to the answer to make it clearer. – Marcel Stimberg Aug 25 '10 at 19:28
  • 2
    Can't upvote it enough! It's so simple and friendly. Available for OS X in homebrew. – Greg Dubicki Mar 17 '17 at 9:33

POSIX sh for loop

Uses sed to rename

for i in image*jpg
do 
  mv -v "$i" "$(echo "$i" | sed -e 's/^\.\/image//' - )"
done
  • Exactly worked for me. Thanks – Ranjith Siji May 16 '16 at 15:46

I like Perl so:

perl -nlE '$old=$_; s/image//; qx(mv $old $_)'

You can also use the same pattern for other tasks like copying the files to another directory:

perl -nlE '$old=$_; s(image)(/path/to/new/dir/); qx(mv $old $_)'
  • 2
    Or (safer!): rename($old,$_) – reinierpost Aug 7 '14 at 11:57

qmv

The command qmv from renameutils opens an editor showing a list of filenames with two colums, separated by a tab. Each row shows one of the filenames, the same in both columns. The right column is representing the new names of the files.
To make changes, edit the names on the right side. In this example, :%s/... or visual block mode are helpful.

Filenames in your editor

$ qmv *.png

In editor:

image0001.png           image0001.png
image0002.png           image0002.png
image0003.png           image0003.png         
~                                             
~                                             
~                                             
~                                             
"/tmp/user/1000/qmvxWyVMs" 3L, 93C

Edit names in right column:
(Removing the image prefix from all lines using visual block mode)

image0001.png           0001.png
image0002.png           0002.png
image0003.png           0003.png         
~                                             
~                                             
~                                             
~                                             
:wq

Log of renaming:

image0001.png -> 0001.png
image0002.png -> 0002.png
image0003.png -> 0003.png

(e.g. Ubuntu: apt-get install renameutils)

recursive

easy recurse selecting image*png files, and assumes no need to deal with newline in file names

find . -name "image*.png" | while read f; do mv -v "$f" "$(echo "$f" | sed -e 's/^\.\/image//' - )"; done

Safe, can deal with spaces, new lines, backslashes and anything else:

find . -name "image*.png" | while IFS= read -r f; do 
   mv -v "$f" "$(echo "$f" | sed -e 's/^\.\/image//' - )"; 
done

POSIX sh using a while loop

Reading names from find command.

find . -maxdepth 1 -type f -name 'image*png' | while IFS= read -r f; do
  mv -v "$f" "$(echo "$f" | sed -e 's/^\.\/image//' - )"
done

Reading names from a file

while IFS= read -r f; do mv -v "$f" "$(echo "$f"|sed -e 's/^\.\/image//' - )"; done < flist

Using shell brace expansion:

for N in {0001..1000}; do mv "{image,}$N.png"; done

For Windows and linux, this Perl script will do; in this case:

$ rnm -l 's/^image//' '*.png'

The script could run recursively under directories and even prepending a count to all of them:

$ rnm -r 's/^/$counter./' '/\.png$/'

UTF-8 chars are also correctly treated, both in Windows and linux.

You can use this tool: rnm (web page)

For your case the command would be:

rnm -rs '/^image//' *.png

You can find more examples/docs here.

Try brename (https://github.com/shenwei356/brename), a practical cross-platform command-line tool for safely batch renaming files/directories via regular expression (supporting Windows, Linux and OS X) .

@patrickDurusau said:

Linux has a variety of batch file renaming options but I didn’t see any short-comings in brename that jumped out at me.

Features:

  • Cross-platform. Supporting Windows, Mac OS X and Linux.
  • Safe. By checking potential conflicts and errors.
  • File filtering. Supporting including and excluding files via regular expression. No need to run commands like find ./ -name "*.html" -exec CMD.
  • Renaming submatch with corresponding value via key-value file.
  • Renaming via ascending integer.
  • Recursively renaming both files and directories.
  • Supporting dry run.
  • Colorful output.

Command:

$ brename -f .png -p image
[INFO] checking: [ ok ] 'image0001.png' -> '0001.png'
[INFO] checking: [ ok ] 'image0002.png' -> '0002.png'
[INFO] checking: [ ok ] 'image0003.png' -> '0003.png'
[INFO] 3 path(s) to be renamed
[INFO] renamed: 'image0001.png' -> '0001.png'
[INFO] renamed: 'image0002.png' -> '0002.png'
[INFO] renamed: 'image0003.png' -> '0003.png'
[INFO] 3 path(s) renamed

ls *png | while read -r f; do f2="`echo $f | sed -e's/image//'`"; mv $f $f2; done

  • Something's not right: "mv: missing destination file operand after 'image0001.png'" – Internet man Aug 24 '10 at 0:06
  • 2
    There are many problems with your code. Parsing the output of ls is just calling for trouble. read should be read -r. all variable substitutions should be within double quotes. – Gilles Aug 24 '10 at 0:20
  • You could write this more effectively as for f in *png; do f2="$(echo "$f" | sed -e 's/image//')"; mv "$f" "$f2"; done. Parsing ls is neither necessary nor a good idea. – kojiro Feb 10 '14 at 4:24

protected by Kusalananda Sep 1 '17 at 8:48

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

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