Search code examples
bashbatch-renamemv

linux - batch move files into a directory and rename those files according to sequential syntax in that directory


I have two directories - A and B - that contain a bunch of photo files. Directory A is where I keep photos long-term, and the files inside are sequentially named "Photo-1.jpg, Photo-2.jpg, etc.".

Directory B is where I upload new photos to from my camera, and the naming convention is whatever the camera names the file. I figured out how to run some operations on Directory B to ensure everything is in .jpg format as needed (imagemagik convert), remove duplicate files (fdupes), etc.

My goal now is to move the files from B to A, and end up with the newly-added files in A sequentially named according to A's naming convention described above.

I know how to move the files into A, and then to batch rename everything in A after the new files have been added (which would theoretically occur every night), but I'm guessing there must be a more efficient way of moving the files from B to A without re-naming all 20,000+ photos every night, just because a few new files were added.

I guess my question is two parts - 1) I found a solution that works (us mv to rename all photos every night), is there any downside to this? and 2) If there is a downside and a more elegant method exists, can anyone help with a script that would look at whatever the highest number that exists in A, then re-name the files, appending onto that number, in B as they are moved over to A?

Thank you!


Solution

  • This bash script will only move and rename the new files from DiretoryB into your DirectoryA path. It also handles file names with spaces and/or any other odd characters in their name in DirectoryB

    #!/bin/bash
    
    aPath="./photos-A"
    bPath="./photos-B"
    aPattern="Photo-"
    
    lNum=$(find $aPath -type f -name "*.jpg" -printf "%f\n" | \
      awk -F'[-.]' '{if($2>m)m=$2}END{print m}')
    while IFS= read -r -d $'\0' photo; do
            mv "$photo" "$aPath/$aPattern$((++lNum)).jpg"
    done < <(find $bPath -type f -name "*.jpg" -print0)
    

    Note

    The command to find the last numbered photo, aka $lNum will run over all 20K+ files, but it should be fairly quick. If it's not, you can always run this once and store the latest number into a file and read from that file.

    Proof of Concept

    $ tree photos-A/
    photos-A/
    ├── Photo-1.jpg
    ├── Photo-2.jpg
    ├── Photo-3.jpg
    ├── Photo-5.jpg
    ├── Photo-6.jpg
    ├── Photo-7.jpg
    └── Photo-8.jpg
    
    0 directories, 7 files
    
    $ tree photos-B/
    photos-B/
    ├── bar.jpg
    ├── baz\ with\ spaces.jpg
    └── foo.jpg
    
    0 directories, 3 files
    
    $ ./mvphoto.sh
    
    $ tree photos-A/
    photos-A/
    ├── Photo-10.jpg
    ├── Photo-11.jpg
    ├── Photo-1.jpg
    ├── Photo-2.jpg
    ├── Photo-3.jpg
    ├── Photo-5.jpg
    ├── Photo-6.jpg
    ├── Photo-7.jpg
    ├── Photo-8.jpg
    └── Photo-9.jpg
    
    0 directories, 10 files