Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Is it possible to write a script to rename a series of file as below:

  • sol-temp_0010.png to sol-temp_1.png
  • sol-temp_0015.png to sol-temp_2.png
  • sol-temp_0020.png to sol-temp_3.png


share|improve this question
What have you tried? We aren't a script writing service and expect that people do some work up front. Copy a few to a new folder and try to make something that works - then if/when you run into issues - let us know what you tried and what issues you saw. – nerdwaller Aug 26 '13 at 22:38
Basic bash solution requires: How to use for loops, file name wildcards, declaring and using integer variables, and the mv command. What have you tried so far, and where are you stuck? – Daniel Beck Aug 26 '13 at 22:59
Have you tried mmv? – cfreire Aug 26 '13 at 22:59

The rename command included with Perl (and thus with many Linux distros, too) can do this easily enough:

rename 's%(\d+)%$1/5-1%e' sol-temp_*.png

The string between the single quotes is evaluated as Perl code and used to modify each filename.

Specifically, s%foo%bar% is a regexp match-and-replace operator. (Usually one would write it as s/foo/bar/, but I wanted to use a slash in the replacement, so I chose a different delimiter.) The regexp (\d+) matches the first sequence of one or more digits in the file name and stores it in the $1 variable for the replacement. The e switch at the end causes the replacement $1/5-1 to be evaluated as a Perl code, so it returns the number stored in $1 divided by 10, minus one.

If you don't happen to have the rename command installed (or if your rename works differently; there are several Unix commands around using that name), but you do have Perl, you can get pretty much the same effect like this:

perl -e 'for (<sol-temp_*.png>) {$o = $_; s%(\d+)%$1/5-1%e; rename $o, $_}'

Note, however, that this version has no error checking or safeguards against overwriting files; those aren't too hard to add, but the do make the code a bit too long for a one-liner. If you don't mind writing a full script, though, something like this ought to work:

use strict;
use warnings;

foreach (<sol-temp_*.png>) {
    my $orig = $_;

    s%(\d+)%$1/5-1%e;   # map "0010" -> "1", "0015" -> "2", etc.

    next if $orig eq $_;
    warn "$0: $_ exists, not renaming $orig\n" and next if -e $_;
    rename $o, $_ or warn "$0: error renaming $orig to $_: $!\n";

(You could even easily modify the script above to read the substitution code and the file names from the command line, just line the rename script does, but that's getting beyond the scope of this answer.)

share|improve this answer

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .