0

There are 32 *.dds files in a folder:

pic-0.dds, pic-1.dds, pic-2.dds,...,pic-31.dds

I'd like to rename them to be:

015040.dds, 015041.dds, 015042.dds,...,0150471.dds.

I'm trying to use the following script:

#!/bin/bash
j=39;
for i in *.dds;
do let j+=1;
mv $i 0150$j.dds;
done

I obtain that pic-0.dds is renamed to 015040.dds, but then it goes wrong, namely pic-1.dds isn't renamed to 015041.dds and so on.

I'd like to have an universal script for other renaming, for example:

pic-40.dds, pic-41.dds, pic-42.dds,...,pic-53.dds

to:

0191.dds, 0192.dds, 0193.dds,...,0204.dds
0

2 Answers 2

1

The problem is pic-*.dds sorts the files asciibetically, not by the number after the dash.

One possible way to fix that is to insert a 0 after the dash to the files named pic-{0..9}.dds. Then listing the files asciibetically will be the same as sorting them by the number and everything will work.

You can do that by using a loop similar to the one you already used:

for f in pic-?.dds ; do
    mv "$f" pic-0"${f#pic-}"
done

The ${f#pic-} is a parameter substitution, the # sign tells the shell to remove the string pic- from the beginning of the variable $f's value.

0
0

There's no need for a shell for loop, you can use perl rename for this.

The perl rename utility is also known as file-rename, perl-rename, or prename, depending on your distribution. It is not to be confused with the rename utility from util-linux which has completely different and incompatible capabilities and command-line options. Perl rename allows you to use any arbitrarily complex perl code to rename files, but is most often used to do simple sed-like s/search/replace/ operations on filenames.

For example:

$ rename -n 's/pic-(\d+)\.dds$/sprintf("015%03i.dds",$1+40)/e' *.dds
rename(pic-0.dds, 015040.dds)
rename(pic-10.dds, 015050.dds)
rename(pic-11.dds, 015051.dds)
rename(pic-12.dds, 015052.dds)
rename(pic-13.dds, 015053.dds)
rename(pic-14.dds, 015054.dds)
rename(pic-15.dds, 015055.dds)
rename(pic-16.dds, 015056.dds)
rename(pic-17.dds, 015057.dds)
rename(pic-18.dds, 015058.dds)
rename(pic-19.dds, 015059.dds)
rename(pic-1.dds, 015041.dds)
rename(pic-20.dds, 015060.dds)
rename(pic-21.dds, 015061.dds)
rename(pic-22.dds, 015062.dds)
rename(pic-23.dds, 015063.dds)
rename(pic-24.dds, 015064.dds)
rename(pic-25.dds, 015065.dds)
rename(pic-26.dds, 015066.dds)
rename(pic-27.dds, 015067.dds)
rename(pic-28.dds, 015068.dds)
rename(pic-29.dds, 015069.dds)
rename(pic-2.dds, 015042.dds)
rename(pic-30.dds, 015070.dds)
rename(pic-31.dds, 015071.dds)
rename(pic-3.dds, 015043.dds)
rename(pic-4.dds, 015044.dds)
rename(pic-5.dds, 015045.dds)
rename(pic-6.dds, 015046.dds)
rename(pic-7.dds, 015047.dds)
rename(pic-8.dds, 015048.dds)
rename(pic-9.dds, 015049.dds)

This captures the digits in the pic-*.dds filenames and adds them to 40 to construct the final filename. The s/search/replace/ substitution operation uses perl's /e modifier to cause it to execute the right-hand-side replacement as perl code. The sprintf function is used to make sure that the calculations are formatted as 3-digit wide zero-padded strings (%03i).

  • this will work regardless of the order it sees the filenames - it doesn't use an incrementing counter, it extracts the existing number from the pic-(\d+).dds$ filenames and adds 40.
  • filenames that don't match that pattern are NOT renamed
  • perl rename will NOT overwrite existing filenames (unless you force it to by using the -f option).

Note that the -n option in the example above makes it a dry run, so it will only show what it would do without actually renaming any files. Remove the -n, or replace it with -v for verbose output, when you've confirmed it does what you want.

0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.