Скрипт Bash для копирования пронумерованных файлов в обратном порядке

У меня есть последовательность файлов:

image001.jpg
image002.jpg
image003.jpg

Можете ли вы помочь мне со скриптом bash, который копирует изображения в обратном порядке, чтобы конечный результат был таким:

image001.jpg
image002.jpg
image003.jpg
image004.jpg  <-- copy of image003.jpg
image005.jpg  <-- copy of image002.jpg
image006.jpg  <-- copy of image001.jpg

Текст в скобках не является частью имени файла.

Зачем мне это нужно? Я создаю видео из последовательности изображений и хотел бы, чтобы видео воспроизводилось «вперед», а затем «назад» (зацикливая полученное видео).


person Alan Turing    schedule 21.08.2011    source источник
comment
Почему бы просто не передать инструменту создания видео список изображений вперед, а затем назад?   -  person Ignacio Vazquez-Abrams    schedule 21.08.2011
comment
Потому что я использую несколько инструментов командной строки, таких как gifsicle (для создания гифок) и ffmpeg (для создания миль на галлон), и работаю с большим количеством (100-200 изображений), которое, вероятно, превысит длину приемлемой команды. Или такого предела нет?   -  person Alan Turing    schedule 21.08.2011
comment
Это зависит от того, как ваш инструмент принимает имена файлов для ввода. К сожалению, кажется, что ffmpeg не может принимать файл, содержащий список имен файлов, в качестве входных данных.   -  person Ignacio Vazquez-Abrams    schedule 21.08.2011
comment
Как и gifsicle :-( Но приведенный ниже скрипт отлично работает.   -  person Alan Turing    schedule 21.08.2011


Ответы (2)


Я думаю, что я бы использовал для этого массив... таким образом, вам не нужно жестко кодировать значение для $MAX.

image=( image*.jpg )
MAX=${#image[*]}
for i in ${image[*]}
do
   num=${i:5:3} # grab the digits
   compliment=$(printf '%03d' $(echo $MAX-$num | bc))
   ln $i copy_of_image$compliment.jpg
done

Я использовал «bc» для арифметики, потому что bash интерпретирует начальные 0 как индикатор того, что число является восьмеричным, а расширение параметра в bash недостаточно мощное, чтобы удалить их без прыжков через обручи. Я мог бы сделать это в sed, но пока я вызывал что-то вне bash, имело смысл выполнять арифметические операции напрямую.

Я предполагаю, что сценарий Кюгельмана мог бы сделать что-то вроде этого:

MAX=(ls image*.jpg | wc -l)

Однако у этого скрипта есть большие проблемы, потому что он перезаписывает половину изображений:

cp image001.jpg image006.jpg # wait wait!!! what happened to image006.jpg???

Кроме того, как только вы превысите 007, вы столкнетесь с восьмеричной проблемой.

person Barton Chittenden    schedule 21.08.2011
comment
Это не удается, если в имени файла есть недопустимый символ, например, подчеркивание. БК это не нравится. - person cde; 08.02.2018

Вы можете использовать printf для печати числа с ведущими 0.

$ printf '%03d\n' 1
001
$ printf '%03d\n' 2
002
$ printf '%03d\n' 3
003

Бросание этого в цикл for дает:

MAX=6

for ((i=1; i<=MAX; i++)); do
    cp $(printf 'image%03d.jpg' $i) $(printf 'image%03d.jpg' $((MAX-i+1)))
done
person John Kugelman    schedule 21.08.2011
comment
Хороший скрипт, но он генерирует избыточные копии. +1 в любом случае. - person Ray Toal; 21.08.2011
comment
В данном случае было бы лучше ln вместо cp файлов. - person glglgl; 21.08.2011
comment
Должно быть for ((i=1; i<=MAX/2; i++)); ? Или я предполагаю, что результат тот же, поэтому более простая версия лучше - person Alan Turing; 21.08.2011
comment
@glglgl, это интересная идея. Не могли бы вы дать команду ln? Я бы сделал символическую ссылку или жесткую ссылку? - person Alan Turing; 21.08.2011
comment
Как и выше, но только ln вместо cp. Если вы хотите сделать символические ссылки (на ваше усмотрение), добавьте -s. Здесь можно использовать оба типа ссылок. - person glglgl; 21.08.2011