The shell sorts the names by the locale order (not necessarily the byte value) of each individual character. Anything that starts with 1
will go before anything that starts with 2
, and so on.
There's two main ways to tackle your problem:
sort -n
(numeric sort) the file list, and iterate that.
- Rename or recreate the target files (if you can), so all numbers are the same length (in bytes/characters). Left pad shorter numbers with
0
(eg. 01
). Then they'll expand like you want.
Using sort
(properly):
mapfile -td '' myfiles <(printf '%s\0' * | sort -zn)
for file in "${myfiles[@]}"; do
# what you were going to do
sort
-z
for zero/null terminated lines is common but not posix. It makes processing paths/data that contains new lines safe. Without -z
:
mapfile -t myfiles <(printf '%s\n' * | sort -n)
# Rest is the same.
Rename the target files:
#!/bin/bash
cd /path/to/the/number/files || exit 1
# Gets length of the highest number. Or you can just hardcode it.
length=$(printf '%s\n' * | sort -n | tail -n 1)
length=${#length}
for i in *; do
mv -n "$i" "$(printf "%.${length}d" "$i")"
done
Examples for making new files with zero padded numbers for names:
touch {000..100} # Or
for i in {000..100}; do
> "$i"
done
If it's your script that made the target files, something like $(printf %.Nd [file])
can be used to left pad the names before you write to them. But you need to know the length in characters of the highest number first (N
).