Batch renaming files

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?

Asked By: Internet man

||

If you are using Bash or other POSIX-compatible shell:

for f in *.png; do
    mv -- "$f" "${f#image}"
done
Answered By: W_Whalley

On Debian and derivatives, Perl’s rename commandline 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
Answered By: Internet man

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'

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 $_)'
Answered By: gvkv

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.

Answered By: Marcel Stimberg

POSIX sh for loop

Uses sed to rename

for i in image*.png
do 
  mv -i -- "$i" "$(printf '%sn' "$i" | sed '1s/^image//')"
done
Answered By: X Tian

POSIX sh using a while loop

Reading names from find command.

find . ! -path . -prune -type f -name 'image*png' |
while IFS= read -r f; do
  mv "$f" "$(printf '%sn' "$f" | sed -e 's/^./image//' - )"
done

Reading names from a file

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

Both of these approaches assume pathnames have no embedded newlines.

Answered By: X Tian

recursive

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

find . -name "image*.png" | while read f; do mv -v "$f" "$(echo "$f" | sed -e 's/image//' - )"; done
Answered By: X Tian

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)

Answered By: Volker Siegel

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.

Answered By: Jahid

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
Answered By: Wei Shen

Using a shells that supports brace expansion (Bash, Zsh, Ksh93, Fish, Csh, Tcsh):

for N in {0001..1000}; do mv "{image,}$N.png"; done
Answered By: αғsнιη

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.

Answered By: circulosmeos

Strangely, no one mentioned this well covered approach:

find . | grep .png$ | sed 'p;s/image//' | xargs -n2 mv

And if you like playing around with arguments:

find . | grep .png$ | sed "p;s/image//" | xargs -n2 sh -c 'echo $1 $2' $0

Single quotes after sh -c matter

Answered By: Nick Roz
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.