Вычтите 1 из всех имен файлов (переименуйте их) в каталог.

У меня есть каталог, содержащий файлы изображений с именами вроде

image1.jpg image2.jpg image3.jpg ... 

К сожалению, имена изображений должны быть основаны на нулевом image1.jpg , поэтому image1.jpg должно быть image0.jpg , image2.jpg должно быть image1.jpg и так далее.

Я могу написать скрипт для генерации mv-команд, подобных этим, поместить их в сценарий оболочки, а затем выполнить их –

 mv image1.jpg image0.jpg mv image2.jpg image1.jpg mv image3.jpg image2.jpg ... 

Но я полагаю, что в Unix есть более аккуратный способ сделать это. Так что это?

Старый добрый переименовать:

 rename 's/(\d+)(\.jpg)/($1-1).$2/e' * 

[Примечание]

Номера изображений должны быть больше 0.

Если изображения больше 9 и не имеют 0, используйте $(ls -v1 *) чтобы избежать сглаживания. Предлагается @arielf и замечен @Graeme.

В случае сомнений используйте также -v для подробных и -n для no-action.

Вы можете передать сгенерированные команды mv в bash . Поэтому вам не нужно копировать их в скрипт и выполнять это. Видеть:

 command_that_generates_mv_commands | bash 

И все будет выполнено, что будет передано в bash .

Вы можете выполнять итерацию на выходе ls, это работает для вашего примера:

 i=0 for file in $(ls *.jpg | sort) ; do mv $file $(echo $file | sed 's/[0-9]*.jpg$/'${i}'.jpg/') i=$((++i)) done 

Вы должны быть на одном пути с вашими файлами

Следующее, похоже, работает на все, что соответствует шаблону imageNUMBER.jpg . Я поставил echo перед командой mv чтобы сначала показать, что будет делать команда; чтобы фактически выполнить переименование, просто удалите echo

 for i in `ls image*.jpg|sort -V` ; do x=`echo $i|sed -e "s/image\(.*\).jpg/\1/"` y=$(( $x - 1 )) echo mv -i $i image$y.jpg done 

В первой строке ls image*.jpg|sort -V приведет к тому, что файлы JPG будут перечислены с восходящими числами в имени файла. Строка x= извлекает номер из имени файла. Затем строка y= уменьшает число на единицу. Имя входного файла и номер y затем используются в команде mv , где флаг -i будет уведомлять вас перед перезаписью файла.

Для моего собственного небольшого теста это произвело выход:

 mv -i image1.jpg image0.jpg mv -i image2.jpg image1.jpg mv -i image123.jpg image122.jpg 

Лично я бы предложил переименовать в другое имя файла, так как теперь порядок обработки файлов может иметь большое значение.

Использование prename perl скрипта, символически переименованного на дистрибутивы на основе Debian, также нуждается в find / sort GNU. Файлы помещаются в порядке возрастания, чтобы предотвратить перезаписи.

 find . -regex '\./image[0-9]+\.jpg' -print0 | sort -zV | xargs -0 rename -n 's/(\d+)\.jpg$/@{[$1-1]}.jpg/' 

Удалите -n только вы убедитесь, что он делает то, что вы хотите. Будет предупреждать о уже существующих файлах перед этим. Однако, пока он показывает, что файлы переименовываются в порядке возрастания, конфликтов при запуске не будет.

С zsh :

 autoload zmv # (in ~/.zshrc) zmv -Qf -n 'image(<->).jpg(n)' 'image$(($1-1)).jpg' 

(удалите -n когда -n счастливы).

(n) – сортировать список численно, поэтому image9.jpg переименовывается до image10.jpg .