Выполнить команду в bash, записать в переменную

time = exec "ffprobe -i /video.mp4 -show_entries format=duration -v quiet -of csv='p=0'"

echo ${time}

Данная команда возвращает продолжительность видео. Вопрос в том. Как выполнить команду и записать возвращаемое ею значение в переменную?

ffmpeg -i /video.mp4 -vf cropdetect -f null - 2>&1 | awk '/crop/ { print  \$NF }' | tail -1

Так получаю

crop=*:*:*:*

Вопрос в том, возможно вместе кропом, получить значение продолжительности. И разбить кроп и время в 2 переменные, отдельно?


Ответы (1 шт):

Автор решения: Vitalizzare

Как выполнить команду и записать возвращаемое ею значение в переменную?

Чтобы сохранить данные, которые программа передает на стандартное устройство вывода, мы используем либо x=$(command ...) либо x=`command ...` (обрамляем команду обратными апострофами). Вокруг знака равенства не должно быть пробелов, иначе это будет интерпретировано как попытка запустить программу, а не присвоить значение переменной.

Как из cropdetect извлечь продолжительность и кроп в переменные?

Вы пытаетесь извлечь время и кроп из результата работы команды:

ffmpeg -i video.mp4 -vf cropdetect -f null - 2>&1

Для этого используете строку обработки последнего фрейма, которая выглядит так:

[Parsed_cropdetect_0 @ 0x55737988da80] x1:0 x2:1919 y1:0 y2:1079 w:1920 h:1072 x:0 y:4 pts:7908 t:0.514844 crop=1920:1072:0:4

Время и кроп расположены в конце строки в виде t:0.514844 crop=1920:1072:0:4. Следовательно в awk мы печатаем не одно, а два последних поля: awk '/crop/ {print $(NF-1), $NF}'. Или не выводим, а сохраняем в две переменные, которые печатаем в конце:

awk '/crop=/ {time=$(NF-1); crop=$NF} 
     END {print substr(time, 3), substr(crop, 6)}'

Здесь substr(x, n) - это часть строки x начиная с позиции n (нумерация начинается с единицы). То есть, команда может выглядеть так:

data=$(ffmpeg -i video.mp4 -vf cropdetect -f null - 2>&1 | 
       awk '/crop=/ {time=$(NF-1); crop=$NF} 
            END {print substr(time, 3), substr(crop, 6)}')
time=$(echo $data | cut -d' ' -f1)
crop=$(echo $data | cut -d' ' -f2)

В последних двух строках мы делим data по пробелу и присваиваем левое/правое поле соответственно переменным time и crop. Впрочем, раз уж мы работаем в bash и у нас всего 2 поля, то можем сделать это отрезая суффикс и префикс по пробелу:

time=${data% *}
crop=${data#* }

Более того, мы могли бы объявить data ассоциативным списком и передать данные в таком формате, который можно использовать при его определении. Это может выглядеть так:

eval declare -A data=(`ffmpeg -i video.mp4 -vf cropdetect -f null - 2>&1 | 
                       awk '/crop=/ {time=$(NF-1); crop=$NF} 
                            END {print "[time]=" substr(time, 3),
                                       "[crop]=" substr(crop, 6)}'`)

Посмотреть содержимое можно командой declare -p data. Извлечь значения: ${data[time]}, ${data[crop]}

→ Ссылка