Bash Script to Rename Files Based on Size

Something like this:

echo "Please rename and press enter"
read rename 

ls |
  # prepend filename with file size in bytes
  parallel stat -c %s,,sep,,%n --  |
  # sort by number
  sort -n |
  # rename to sequencenumber followed by size in bytes
  parallel -q --colsep ,,sep,, mv {2} "$rename"{#}_{1}

The main trick is to replace

    for i in *.jpg

with

    for i in $(ls -S *.jpg)

however, as Kusalananda's pointed out, this assumes "educated" file names (no spaces, no control characters), so here is a different approach:

count=1
ls -S --escape *.jpg | while read f; do
    n=$(printf "%04d" $count)
    ((count++))
    mv --no-clobber "$f" "$rename$n.jpg"
done

-S sorts by decreasing file size
--escape prevents names with embedded newlines causing damage
--no-clobber prevents overwriting destination files in case the script is run twice

P.S. Ole Tange's answer is a very nice efficient way of doing the same, but you probably won't see the difference unless you routinely rename thousands files.


In the zsh shell:

typeset -Z 3 count=0
for name in *.jpg(.DNOL); do
    count=$(( count + 1 ))
    mv -i -- "$name" "a$count.jpg"
done

This would iterate over all regular files with an .jpg filename suffix in the current directory, in the order of largest to smallest. For each file, it would rename it to aNNN.jpg where NNN is the zero-filled integer count of files processed so far.

The (.DNOL) glob qualifier orders the matching filenames in the correct order using OL ("revers order by length"), and selects only regular files (including hidden names) using .D ("regular files, and dot-files"). The N makes the pattern expand to nothing if there is no matching name ("null glob").

This would work on all valid filenames on any Unix system with zsh installed.

To use this from bash:

zsh -c 'typeset -Z 3 count=0
for name in *.jpg(.DNOL); do
    count=$(( count + 1 ))
    mv -i -- "$name" "a$count.jpg"
done'

If you have a variable $rename that you want to pass in as a filename prefix instead of using a:

zsh -c 'typeset -Z 3 count=0
for name in *.jpg(.DNOL); do
    count=$(( count + 1 ))
    mv -i -- "$name" "$1$count.jpg"
done' zsh "$rename"

Note that the zsh on the last line is not a typo and that the value of $rename is used as $1 inside the zsh -c script.

Tags:

Rename