Armin
Armin

Reputation: 13

How can I batch rename multiple images with their path names and reordered sequences in bash?

My pictures are kept in the folder with the picture-date for folder name, for example the original path and file names:

.../Pics/2016_11_13/wedding/DSC0215.jpg
.../Pics/2016_11_13/afterparty/DSC0234.jpg
.../Pics/2016_11_13/afterparty/DSC0322.jpg

How do I rename the pictures into the format below, with continuous sequences and 4-digit padding?

.../Pics/2016_11_13_wedding.0001.jpg
.../Pics/2016_11_13_afterparty.0002.jpg
.../Pics/2016_11_13_afterparty.0003.jpg

I'm using Bash 4.1, so only mv command is available. Here is what I have now but it's not working

#!/bin/bash

p=0
for i in *.jpg;
do
  mv "$i" "$dirname.%03d$p.JPG"
  ((p++))
done

exit 0

Upvotes: -1

Views: 388

Answers (2)

muru
muru

Reputation: 4897

Using only mv and bash builtins:

#! /bin/bash

shopt -s globstar
cd Pics
p=1
# recursive glob for .jpg files
for i in **/*.jpg
do
    # (date)/(event)/(filename).jpg
    if [[ $i =~ (.*)/(.*)/(.*).jpg ]]
    then
        newname=$(printf "%s_%s.%04d.jpg" "${BASH_REMATCH[@]:1:2}" "$p")
        echo mv "$i" "$newname"
        ((p++))
    fi
done

globstar is a bash 4.0 feature, and regex matching is available even in OSX's anitque bash.

Upvotes: 1

Let say you have something like .../Pics/2016_11_13/wedding/XXXXXX.jpg; then go in directory .../Pics/2016_11_13; from there, you should have a bunch of subdirectories like wedding, afterparty, and so on. Launch this script (disclaimer: I didn't test it):

#!/bin/sh
for subdir in *; do                # scan directory
  [ ! -d "$subdir" ] && continue;  # skip non-directory
  prognum=0;                       # progressive number
  for file in $(ls "$dir"); do     # scan subdirectory
    (( prognum=$prognum+1 ))          # increment progressive
    newname=$(printf %4.4d $prognum)  # format it
    newname="$subdir.$newname.jpg"    # compose the new name
    if [ -f "$newname" ]; then        # check to not overwrite anything
      echo "error: $newname already exist."
      exit
    fi

    # do the job, move or copy
    cp "$subdir/$file" "$newname"

  done
done

Please note that I skipped the "date" (2016_11_13) part - I am not sure about it. If you have a single date, then it is easy to add these digits in # compose the new name. If you have several dates, then you can add a nested for for scanning the "date" directories. One more reason I skipped this, is to let you develop something by yourself, something you can be proud of...

Upvotes: 1

Related Questions