zcaudate
zcaudate

Reputation: 14258

renaming images into an ordered sequence using shell

I have a bunch of folders containing images that are in order but are not sequential like this:

/root
  /f1
    img21.jpg
    img24.jpg
    img26.jpg
    img27.jpg
  /f2
    img06.jpg
    img14.jpg
    img36.jpg
    img57.jpg

and I want to get them looking like this, having the folder title as well as having all the images in sequential order:

/root
  /f1
    f1_01.jpg
    f1_02.jpg
    f1_03.jpg
    f1_04.jpg
  /f2
    f2_01.jpg
    f2_02.jpg
    f2_03.jpg
    f2_04.jpg

I'm not sure how to do this using shell script.

Thanks in advance!

Upvotes: 1

Views: 137

Answers (2)

Use a for loop to iterate over the directories and another for loop to iterate over the files. Maintain a counter that you increment by 1 for each file.

There's no direct convenient way of padding numbers with leading zeroes. You can call printf, but that's a little slow. A useful, fast trick is to start counting at 101 (if you want two-digit numbers — 1000 if you want 3-digit numbers, and so on) and strip the leading 1.

cd /root
for d in */; do
  i=100
  for f in "$d/"*; do
    mv -- "$f" "$d/${d%/}_${i#1}.${f##*.}"
    i=$(($i+1))
  done
done

${d%/} strips / at the end of $d, ${i#1} strips 1 at the start of $i and ${f##*.} strip everything from $f except what follows the last .. These constructs are documented in the section on parameter expansion in your shell's manual.

Note that this script assumes that the target file names will not clash with the names of existing files. If you have a directory called img, some files will be overwritten. If this may be a problem, the simplest method is to first move all the files to a different directory, then move them back to the original directory as you rename them.

Upvotes: 2

larsks
larsks

Reputation: 311665

Within a directory, ls will give you files in lexical order, which gets you the correct sort. So you can do something like this:

let i=0
ls *.jpg | while read file; do
    mv $file prefix_$(printf "%02d" $i).jpg
    let i++
done

This will take all the *.jpg files and rename them starting with prefix_00.jpg, prefix_01.jpg and so forth.

This obviously only works for a single directory, but hopefully with a little work you can use this to build something that will do what you want.

Upvotes: 2

Related Questions