I have a collection of images which are scanned pages of books. They total some 10,000 pages. The books were printed bilingually, with the text and translation on facing pages. The translation has been discarded, and there is only the original text pages, which are the even numbered pages.

I need the file names to include the correct page number, whereas currently they are in a simple sequence. Happy to use rename or similar.

To make it explicit, we currently have file numbering of the form:


Where the first number 1 is the volume number; this is to remain unchanged. The second number is the page number, and this needs to be changed thus:

  • What if the the input filename is 1-259.png Dec 1 '14 at 3:36
  • @AvinashRaj I'm not OP but I think that would be 1-518.png. and 1-260.png to 1-520.png and etc. In general case this format of name 1-num.png has been change to 1-num*2.png. Dec 1 '14 at 6:08
  • 1
    If you do a mv 1-001.png 1-002.png than 1-002.png will be overwritten by 1-001.png. You should be aware of that. On way to overcome this is to start with the highest number.
    – miracle173
    Dec 1 '14 at 8:06

Here is the rename command:

rename -n 'our $i=2;s/^(\d+)-(\d+)/sprintf("$1-%04d", $i*$2)/e' *.png


1-001.png renamed as 1-0002.png
1-002.png renamed as 1-0004.png
1-003.png renamed as 1-0006.png
1-004.png renamed as 1-0008.png
1-005.png renamed as 1-0010.png
2-001.png renamed as 2-0002.png
2-002.png renamed as 2-0004.png
2-003.png renamed as 2-0006.png
2-004.png renamed as 2-0008.png
2-005.png renamed as 2-0010.png
-n, --no-act 
            No Action: show what files would have been renamed.

With our $i I defined a perl global variable and I set its value with 2.

(\d+)-(\d+): (\d+) is matching the beginning of the files name with one or more numbers of digit and make it as group capture and one -; then again with (\d+) match any number after dash(-) in files name and make it as group capture.

^ in the beginning of ^(\d+)-(\d+) makes sure to avoiding/skipping rename files if they are not start(^) with numbers like a11.001.png and renames files only if they starts with digit-digit.png.

sprintf("$1-%04d", $i*$2): First print group capture with index $1(or its back-reference) (refer to first (\d+) in ^(\d+)-(\d+)) then print new calculated value of group $2 with maximum 4 field width(%4d) and fill empty fields with 0s(%04d).

Note: Why I used %04d in sprintf command, because when you want to rename 1-001.png to 1-002.png, file 1-002.png already exist and you can not rename it. So I added a extra zero to front of the second field to avoiding this error.

Or as @muru suggests, you can use back-references instead of the global variable

rename -n 's/^(\d+)-(\d+)/sprintf("$1-%04d",$2*2)/e' *.png

$1 is the back-reference of first (\d+) and $2 is the back-reference of second (\d+). Note that you have to use pair of parentheses (group) to make it as a group capture.

At the end you can remove -n option from command to rename on your files.

  • Suggestion: Instead of the global variable thing, use backreferences: rename -n 's/^1-(\d+)/sprintf("1-%04d",$1*2)/e'
    – muru
    Dec 1 '14 at 18:01
  • The version as amended by muru did the trick. With the original script by KasiyA, the numbering continued increasing even over multiple volumes, not restarting the page numbering with each volume as it should. Eg. if I have 1-001.png, 1-002.png, ... 1-100.png, 2-001.png, 2-002.png, and so on, @Kasiya's original script creates: 1-002.png, 1-004.png, ... 1-200.png, 2-202.png, 2-204.png, etc. The version as amended following muru gives me 1-002.png, 1-004.png, ... 1-200.png, 2-002.png, 2-004.png, which is what I'm after.
    – sujato
    Dec 5 '14 at 11:24
  • @user2360490 Updated answer. I though all your files starts with 1-....png. now fixed as what you wanted. Dec 5 '14 at 12:08

Working under the assumption that you want to multiply each page number by 2,


tmpext=tmpext # temporary extension to avoid clobbering existing files

# double the page number and change .png to tmpext
for page in ./*-[[:digit:]][[:digit:]][[:digit:]].png; do
  tmppage=${vol}-$(printf %.3d $((num * 2))).$tmpext
  mv -vi "$page" "$tmppage"

# move .tmpext back to .png
for tmppage in ./*."$tmpext"; do
  mv -vi "${tmppage}" "${tmppage%$tmpext}png"
  • You strip the last file name to 1-.png. Dec 1 '14 at 15:54
  • @KasiyA I am not sure what you mean. What file name?
    – jw013
    Dec 1 '14 at 16:53
  • Do touch 1-{001..008}.png and run your script. As you see one of file name(I think it's last file) renames to 1-.png. Dec 1 '14 at 17:25
  • @KasiyA I see, the leading zeroes were being interpreted as octal numbers. Stripping out the leading zeroes seemed like the easiest way to fix that issue.
    – jw013
    Dec 1 '14 at 17:44

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.