I have a large collection of image files, for example:

a.png, b.png, c.png, etc

If I have a file with mappings of filenames to numbers, like so (ignore the format, it could be anything):


Is there any easy way to batch rename all the files using the mapping file to:

1.png, 2.png, 3.png, etc

I'm looking for unix/linux commands. I know I can write a very simple script, but just curious if there is any other technique.



There isn't a single command for everything; that's the point of having a scriptable shell.

while read -r old new; do
    mv "$old.png" "$new.png"
done < map.txt
  • But I want one command. Something like, "renamefilesfrommappingfile <mappingfile> ." :) – Steve Apr 28 '11 at 17:51
  • 4
    @steve: renamefilesfrommappingfile() { local old new; while read -r old new; do mv "$old" "$new"; done < "$1"; } – grawity Apr 28 '11 at 17:52
  • Haha. Good one. – Steve Apr 28 '11 at 17:57
  • 1
    You could make this a bit more general by playing with $IFS before and after the while loop; – Steven D Apr 28 '11 at 18:38
  • Missing colon (;) after "$new.png". Too little for SE to accept the correction. – André Levy Jun 27 '18 at 7:24

Without sed, you may do replacements like this in bash:

for line in  $(< patterns) ; do  echo "Pattern: " $line " char: "  ${line/=>*/} " nr: " ${line/*=>/}; done 

('patterns' would be the file with a=>1 and so on) which leads to:

for line in  $(< patterns) ; do
  mv $c.png $n.png 

The manpage of bash lists this and other, interesting options under 'string substitution'.

Maybe perls rename is an interesting option too. It allows mass renamings with patterns, like

rename 's/^a/1/' a*png 

On ubuntu, it comes with the perl-package, afaik.


This is one way with perl:

cat mapfile | perl -e 'my$h={eval join(",",<>)};while (($k,$v)=each%$h){`mv $k.png $v.png`}'

Second try:

perl -nle '(@a=map{s/^\s+//;s/\s+$//;s/'/\\'/g;$_}split/\s*=>\s*/,$_,2)and`mv \'$a[0].png\' \'$a[1].png\'`'

Works with:

Someone's $tupid file name    =>   renamed by "simple" script?!
  • -1 for eval'ing the input, for eval'ing barewords on the right side of =>, and for using `mv` instead of whitespace-safe rename(). – grawity Apr 28 '11 at 17:58
  • 1
    Why not something like: perl -nle 'my ($old, $new) = split /=>/; rename "$old.png", "$new.png"' mapfile. Another advantage of avoiding eval is that you can actually change the pattern as the question indicates may be necessary. – Steven D Apr 28 '11 at 18:20
  • @grawity: perldoc rename: Behavior of this function varies wildly depending on your system implementation. For example, it will usually not work across file system boundaries, even though the system mv command sometimes compensates for this. Other restrictions include whether it works on directories, open files, or pre-existing files. Check perlport and either the rename(2) manpage or equivalent system documentation for details.[italics mine] – Axeman Apr 28 '11 at 18:22
  • @Axeman: thanks for the heads up on rename! But the eval is still ugly. – Steven D Apr 28 '11 at 18:24
  • 1
    @Axeman: Use File::Copy to copy or move files on all but antique versions of Perl. – Gilles Apr 28 '11 at 19:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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