сортировка имен файлов численно, когда у них есть нечисловой префикс

У меня есть файлы в следующем формате: x1 x2 ... x10 x11 ... x101 ...

Я хочу переименовать эти файлы, поэтому они имеют одну и ту же длину имени: x001 x002 ... x010 ...

Я могу сделать это с файлами, у которых нет нечислового префикса (просто используя sort -n за которым следует while read x; ), но сортировка не распознает числовое значение, если оно не находится в начале имя файла.

Вы можете попробовать отсортировать файлы, используя опцию v (версия) ls например ls -1v . Или вы можете использовать числовую сортировку с x в качестве разделителя: ls | sort -n -t 'x' +1 ls | sort -n -t 'x' +1

Но вам не нужно сортировать файлы для их переименования. Вы можете просто посмотреть длину имени файла и поместить его нулями, если это необходимо. Вот небольшой скрипт, который делает это:

 prefix=x maxLength=4 for file in ${prefix}* do if [ ${#file} -lt $maxLength ] then newFile=$file while [ ${#newFile} -lt $maxLength ] do newFile=${newFile/$prefix/${prefix}0} done mv $file $newFile fi done 

Вы уверены, что вам нужно сначала отсортировать их?

 m=0 for f in x*; do [ "${#f}" -gt "$m" ] && m=${#f} done for f in x*; do echo mv -- "$f" "${f%${f#?}}$( printf '%0.*d' $(( m - 1 )) "${f#?}" )" done 

Если ваша реализация printf не поддерживает указанный выше синтаксис, используйте printf "%0.$(( m - 1 ))d" "${f#?}" .

Удалите эхо при выполнении.

Чтобы уточнить ответ собаки, sort имеет вариант сортировки версии. Обратите внимание, что некоторые платформы (например, busybox) не имеют этой опции.

Вы можете использовать его так:

 sort -V sort --version-sort 

Или версия сортирует n-й столбец:

 sort -knV 

Вам нужно переименовать, в то время как есть похожие инструменты, которые могут вам тоже помочь:

 touch x1 x2 x10 x11 x101 ls ; rename 's/x/x0/' x[0-9] 

x1 x10 x101 x11 x2

 ls ; rename 's/x/x0/' x[0-9][0-9] 

x01 x02 x10 x101 x11

 ls 

x001 x002 x010 x011 x101

«rename» является частью некоторого пакета perl, если вам нужно его установить, по крайней мере, для Linux.

Без переименования существует аналогичное решение с циклом:

 rm * touch x1 x2 x10 x11 x101 for f in x[0-9] ; do mv $f ${f/x/x0}; done for f in x[0-9][0-9] ; do mv $f ${f/x/x0}; done ; ls 

x001 x002 x010 x011 x101