Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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):

a=>1
b=>2
c=>3
...

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.

Thanks

share|improve this question
add comment

3 Answers 3

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
share|improve this answer
    
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
add comment

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
  c=${line/=>*/}
  n=${line/*=>/}
  mv $c.png $n.png 
done 

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.

share|improve this answer
add comment

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?!
share|improve this answer
    
-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
show 5 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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