Xixor
Xixor

Reputation: 23

Batch rename all files in a directory to basename-sequentialnumber.extention

I have a directory containing .jpg files, currently named photo-1.jpg, photo-2.jpg etc. There are about 20,000 of these files, sequentially numbered.

Sometimes I delete some of these files, which creates gaps in the file naming convention.

Can you guys help me with a bash script that would sequentially rename all the files in the directory to eliminate the gaps? I have found many posts about renaming files and tried a bunch of things, but can't quite get exactly what I'm looking for.

For example:

photo-1.jpg
photo-2.jpg
photo-3.jpg

Delete photo-2.jpg

photo-1.jpg
photo-3.jpg

run script to sequentially rename all files

photo-1.jpg
photo-2.jpg

done

Upvotes: 1

Views: 299

Answers (1)

Jetchisel
Jetchisel

Reputation: 7801

With find and sort.

First check the output of

find directory -type f -name '*.jpg' | sort -nk2 -t-

If the output is not what you expected it to be, meaning the order of sorting is not correct, then It might have something to do with your locale. Add the LC_ALL=C before the sort.

find directory -type f -name '*.jpg' | LC_ALL=C sort -nk2 -t-

Redirect it to a file so it can be recorded, add a | tee output.txt after the sort

Add the LC_ALL=C before the sort in the code below if it is needed.

#!/bin/sh

counter=1

find directory -type f -name '*.jpg' |
  sort -nk2 -t- | while read -r file; do
  ext=${file##*[0-9]} filename=${file%-*}
  [ ! -e  "$filename-$counter$ext" ] &&
  echo mv -v "$file" "$filename-$counter$ext"
  counter=$((counter+1))
done # 2>&1 | tee log.txt
  • Change the directory to the actual name of your directory that contains the files that you need to rename.
  • If your sort has the -V flag/option then that should work too.
  • sort -nk2 -t- The -n means numerically sort. -k2 means the second field and the -t- means the delimiter/separator is a dash -, can be written as -t -, caveat, if the directory name has a dash - as well, sorting failure is expected. Adjust the value of -k and it should work.
  • ext=${file##*[0-9]} is a Parameter Expansion, will remain only the .jpg
  • filename=${file%-*} also a Parameter Expansion, will remain only the photo plus the directory name before it.
  • [ ! -e "$filename-$counter$ext" ] will trigger the mv ONLY if the file does not exists.
  • If you want some record or log, remove the comment # after the done
  • Remove the echo if you think that the output is correct

Upvotes: 1

Related Questions