llin
llin

Reputation: 38

swap filenames when their substring match

There are 1000+ images in folder1 with filenames "Firstname_Lastname_0032somenumber.jpg". I have to replace some of those images with 200+ updated images in folder2 with filenames "firstname lastname.jpg"

So I'm trying to work on a bash script to do this, but I couldn't complete

  1. store filenames into 2 arrays (arr1, arr2)

     shopt -s nullglob 
     arr1=(folder1/*)
     arr2=(folder2/*)
    
  2. get the substring of the filename (firstname/lastname) of each element in the arr1

    for i in "${arr1[@]}"
     do
       echo "$i" | cut -d'/' -f 2 | cut -d'_' -f 1 |  tr '[:upper:]' '[:lower:]'
    done
    
  3. check the substring whether matches to the substring in the arr2

  4. rename the file

Upvotes: 1

Views: 37

Answers (2)

clearlight
clearlight

Reputation: 12615

My approach might be something more like reading the files in a loop from folder1 one at a time, stripping off the leading part of the path from the file (you can use basename and dirname commands to split off path components), then splitting file name into tokens, recombining the tokens and copying them to folder2 by appending the fixed up file name to that string.

for path in $(ls "folder1/"*); do {
  file=$(/usr/bin/basename path)
  firstAndLast=${file%_*}
  first=${firstAndLast%%_*}
  last=${firstAndLast##*_}
  outputPath=folder2/${first}${last}.jpg
}

You can also translate the string alphabetic case, of course, similar to what you've done. You should be able to find basename and dirname in /usr/bin or /bin in a *NIX system.

Upvotes: 0

Aaron Digulla
Aaron Digulla

Reputation: 328624

A better solution would be associative arrays. The first step is like your code in step #2 to create an array where the file names from folder1 are keys:

declare -A map
for i in "${arr1[@]}"; do
   key=$(basename "$i" | cut -d'_' -f 1-2 |  tr '[:upper:]' '[:lower:]' | tr '_' ' ')
   map[$key]="$i"
done

This converts Firstname_Lastname_0032somenumber.jpg to firstname lastname (all lower case, _ replaced by space).

Now you loop over the files in folder 2, process them in a similar way to get the key to fetch the new file name:

for i in "${arr2[@]}"; do
   key=$(basename "$i" .jpg | tr '[:upper:]' '[:lower:]')
   newName=${aa[$key]}
   if [[ -n "$newName" ]]; then
       echo "mv \"$folder2/$i\" \"$folder1/$newName\""
   fi
done

Related:

Upvotes: 2

Related Questions