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 (за създаване на gifs) и ffmpeg (за създаване на mpg) и работя с голям брой (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 интерпретира водещите нули като индикатор, че числото е осмично, а разширяването на параметъра в bash не е достатъчно мощно, за да ги премахне, без да прескача обръчи. Можех да направя това в sed, но докато извиквах нещо извън bash, имаше също толкова смисъл да правя аритметиката директно.

Предполагам, че скриптът на Kuegelman би могъл да направи нещо подобно:

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
Това се проваля, ако в името на файла има незаконен знак, като долна черта. BC не го харесва. - person cde; 08.02.2018

Можете да използвате printf, за да отпечатате число с водещи нули.

$ 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