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.