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

17

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

image1.jpg 
image2.jpg 
image3.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 есть более удобный способ сделать это. Так что же это?

Wes
источник
6
На самом деле это самый простой способ сделать это, если нет пробелов. ( for i in $(seq 0 100); do mv image$[i+1].jpg image$i.jpg; done)
Рикки Бим
5
Важен ли порядок изображений? Если нет, просто переименуйте последнее изображение из imageN.jpgв image0.jpgи все готово.
Jnovacho
@jnovacho, довольно умно! Но да, порядок изображений важен.
Уэс

Ответы:

20

Старый добрый perl переименуйте:

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

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

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

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

В случае сомнений используйте также -vдля многословия и -nдля бездействия.


источник
Что означает «е»?
Уэс
3
'e' означает оценку, будет заменен раздел замены. смотрите такжеperlreref
6
Файлы должны быть переданы в порядке возрастания, чтобы избежать путаницы. Это будет хорошо работать, только если есть менее 10 файлов (или если числа имеют начальные нули).
Грэм,
Я уже заметил это, также не должно быть 0в источниках.
2
замените *в конце, `ls -v1 *`и вы будете более защищены от ударов. Это пойдет от самого низкого числа до самого высокого.
Ариэльф
6

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

command_that_generates_mv_commands | bash

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

хаос
источник
Это не аккуратно. :)Решает проблему, так что +1.
JMCF125
5

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

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

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

babasbot
источник
1
Лучше использовать -iили -nс ним mv, это предотвратит перезапись в крайних случаях.
Грэм,
не sort -Vбудет лучше вместо этого?
user80551
sortне будет работать, он будет показывать , image10.jpgпрежде чем image1.jpgчто может быть проблемой. Вам нужно, sort -nk 1.8как в ответе @ Грэм.
Тердон
@ user80551, sort -Vхорошая идея, добавлю ее в мой ответ. Однако могут быть и другие крайние случаи, просто хороший совет - добавлять подобные варианты с такими вопросами на тот случай, если кто-то копирует и в итоге наносит какой-то ущерб.
Грэм
4

Следующее, кажется, работает для всего, что соответствует шаблону 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

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

BRM
источник
1
Лучше использовать -iили -nс ним mv, это предотвратит перезапись в крайних случаях.
Грэм,
Очень хорошее предложение, я отредактирую ответ
BRM
В macOS, вы должны использовать sort -n, -Vопция не существует.
Винсент Сидит
4

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

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

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

Graeme
источник
Файл уже существует проблемы с этим.
Уэс
4

С zsh:

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

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

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

Стефан Шазелас
источник