I've got a folder /User/me/Desktop/folder/images
with files like key 1--name.jpg
, key 10--name1.jpg
, etc. The files are sorted incorrectly when fed to my site so I get an arrangement like key 84--name.jpg -> key 9--name.jpg -> key 94--name.jpg
instead of key 9--name.jpg -> key 84--name.jpg -> key 94--name.jpg
because of character precedence. So I wan to replace all the non-three-digit-length image names like 9, 12, 99
with their three-digit, 0-padded equivalents to get 009, 012, 099
so the ordering will be correct. How can this be done for folder full of files in one line in my Mac terminal.
-
Please see the accepted answer on THIS POST. You need to do some homework, like parsing the file name and extracting the sequence number and reforming the filename but you can figure out the logic.– MelBurslanMar 22, 2016 at 20:41
3 Answers
Extraxt the number, something like:
$ echo 'key 88--name.jpg' | sed 's/key \([0-9]\+\)--.*/\1/'
88
Format it with printf:
$ printf '%04d' "88"
0088
reinsert that into the name:
$ echo 'key 88--name.jpg' | sed 's/\(key [0-9]\+--\)/key 0088--/'
key 0088--name.jpg
All in one script:
#!/bin/sh
for f in 'key '*'--name.jpg'; do
a="$( echo "$f" | sed 's/key \([0-9]\+\)--.*/\1/' )"
b="$( printf '%04d' "$a" )"
c="$( echo "$f" | sed 's/\(key '"$a"'--\)/key '"$b"'--/' )"
echo \
mv -i "$f" "$c"
done
Or even faster:
#!/bin/sh
for f in 'key '*'--name.jpg'; do
a="${f#key }"
a="${a%--name.jpg}"
b="$( printf 'key %04d--name.jpg' "$a" )"
echo \
mv -i "$f" "$b"
done
Both scripts will not change anything. They will just list what is going to be changed. If you are happy with what you see, just comment out (add a # in front of) the line echo \
. In any case, the mv command will not overwrite any file if the file already exists (the -i option).
If you know in advance how many digits to pad to, this can be done fairly simply by combining the shell's string manipulation and arithmetic features. To pad to 3 digits, number from 1000 and strip away the leading 1
.
for current_name in *[0-9]*; do
# Split the name into prefix, digits, suffix
prefix=${current_name%%[0-9]*}; suffix=${current_name#"$prefix"}
# Pad the digits
digits=${suffix%%[!0-9]*}; suffix=${suffix#"$digits"}
digits=$((digits+1000)); digits=${digits#1}
# Rename the file
new_name="$prefix$digits$suffix"
if [ "$new_name" != "$current_name" ]; then
mv -- "$current_name" "$new_name"
fi
done
The following function computes the number of necessary digits (1 for up to 9 files, 2 for up to 99 files, a.s.o.) and renames the files with the first number in the filename padded with zeros accordingly:
pad_numbers_with_zeros(){
folder="$1"
[[ -d "$folder" ]] || { echo 'need directory argument' && return; }
extension="$2"
[[ -z "$extension" ]] && extension=wav
digits="$3"
if [[ -z "$digits" ]]; then
amount=$(ls "$folder"/*.$extension | wc -l)
digits=$(echo "l($amount)/l(10)+1" | bc -l)
fi
fmt=$(printf '%%0%dd' $digits)
for f in "$folder"/*.$extension; do
bn=$(basename "$f")
number=$(echo $bn | sed -re 's/^[^[:digit:]]*0*([[:digit:]][[:digit:]]*)[^[:digit:]].*/\1/')
[[ "$bn" == "$number" ]] && continue
pf_pat=$(echo $bn | sed -re "s/0*$number/$fmt/")
new_path=$(printf "$folder/$pf_pat" $number)
[[ "$f" != "$new_path" ]] && mv -i "$f" "$new_path"
done
}
For .jpg
-files call with a second argument jpg
. This makes of course only sense if filenames have consecutive numbers in them. Alternatively the number of desired digits can be passed as third argument.