RandomWhiteTrash
RandomWhiteTrash

Reputation: 4014

Bash script for renaming files to consecutive numbers in multiple directories

I have a catalogue structure like this:

AD
 -> AD01
   -> DSC123.jpg
   -> DSC124.jpg
 -> AD02
   -> DSC234.jpg
   -> DSC1455.jpg
 -> AD03
  ->...
 -> AD04
  ->...
 ->...
AE
 ->...
...

No I would like to run a script that will traverse whole tree and rename each folder files to be a consecutive numbers 01.jpg, 02.jpg... etc.

I found something like this to help with consecutive numbers:

find -name '*.jpg' | gawk 'BEGIN{ a=1 }{ printf "mv %s %02d.jpg\n", $0, a++ }' | bash 

but how do I make it run on all the folders recursively, throughout the tree (there are like 1000 of folders each with about 6-20 files).

Edit: Result should look like this:

AD
 -> AD01
   -> 01.jpg
   -> 02.jpg
 -> AD02
   -> 01.jpg
   -> 02.jpg
 -> AD03
  ->...
 -> AD04
  ->...
 ->...
AE
 ->...
...

Upvotes: 0

Views: 1055

Answers (4)

Gilles Quénot
Gilles Quénot

Reputation: 185161

The shortest one using :

cd AD/AD02
rename -n 'no strict; s@.*(?=\.)@sprintf "%0.2d", ++$x@e' *.jpg

Remove -n switch when the output looks good.

warning There are other tools with the same name which may or may not be able to do this, so be careful.

The rename command that is part of the util-linux package, won't.

If you run the following command (GNU)

$ file "$(readlink -f "$(type -p rename)")"

and you have a result that contains Perl script, ASCII text executable and not containing ELF, then this seems to be the right tool =)

If not, to make it the default (usually already the case) on Debian and derivative like Ubuntu :

$ sudo apt install rename
$ sudo update-alternatives --set rename /usr/bin/file-rename

If you don't have this command with another distro, search your package manager to install it or do it manually (no deps...)


This tool was originally written by Larry Wall, the Perl's dad.

Upvotes: 1

sat
sat

Reputation: 14949

You can try this bash script,

#!/bin/bash
for dir in $(find -type d \( ! -name '.*' \)) 
do 
  i=1; 
  for file in $(find "$dir" -name '*.png')
  do 
     a=$(printf "%02d" $i)
     new=${file%/*}
     echo "mv $file $new/$a.png"
     let i=i+1
  done 
done

It will list out the mv commands that is going to apply. See whether it is giving what you expected. Finally, replace the echo with mv command.

Upvotes: 0

dave sines
dave sines

Reputation: 11

Use find to find the directories then cd into each directory in turn and rename the files.

find /path/to/catalogue -type d -exec bash -c '
  shopt -s nullglob
  for dir in "$@" ; do
    ( cd "$dir" || exit
      files=( *[!0-9]*.jpg )
      for (( n = 0 ; n < "${#files[@]}" ; n++ )) ; do
        printf -v target '%02d.jpg' $(( n + 1 ))
        mv -- "${files[$n]}" "$target"
      done )
  done
' bash {} +

Upvotes: 1

Jayesh Bhoi
Jayesh Bhoi

Reputation: 25885

#!/bin/bash
files=$(find . -name "*.jpg" -type f)
a=1
for i in $files; do
  dir=$(dirname "$i")
  new=$(printf "%04d" ${a}) 
  mv ${i} $dir/${new}.jpg
  let a=a+1
done

Upvotes: 0

Related Questions