sh может выполнять только целочисленную арифметику, поэтому вам придется использовать что-то еще, напримерbc
(или язык, который не может -целочисленную арифметику, такой как awk или perl ).
Чтобы использовать bc
, сначала необходимо преобразовать формат %H :%M :%S.%3N в секунды (, включая десятичную дробь ), а затем передать это в bc
.
Например:
#!/bin/bash
epoch='1970-01-01'
len1='00:01:01.111'
len2='00:02:02.222'
# convert to seconds
len1_s=$(date -u -d "$epoch $len1" '+%s.%3N')
len2_s=$(date -u -d "$epoch $len2" '+%s.%3N')
# add the seconds
sum_s=$( echo "$len1_s + $len2_s" | bc )
echo $len1_s + $len2_s = $sum_s
# convert back to H:M:S.N
sum=$(date -u -d "@$sum_s" '+%T.%3N')
echo $len1 + $len2 = $sum
Выход:
$./sum.sh
61.111 + 122.222 = 183.333
00:01:01.111 + 00:02:02.222 = 00:03:03.333
Я оставлю реализацию этого в вашем цикле while вам.... но отмечу, что lsdvd
имеет несколько полезных параметров вывода, которые дадут вам длину глав в секундах (, так что вам не нужно преобразовать их ). Вероятно, наиболее полезным является параметр вывода XML, который затем можно обработать с помощью xmlstarlet
или xml2
для извлечения длин глав.
напр. здесь lsdvd
вывод XML, преобразованный в формат, ориентированный на строку -(, подходящий для обработки с помощью awk или чего-либо еще )с использованиемxml2
:
Это примерно 48-минутное видео с 11 главами, большая часть которых длится примерно 5 минут (300 секунд ).
$ lsdvd -c -Ox '/path/to/some/dvd.iso' | xml2
/lsdvd/device=/path/to/some/dvd.iso
/lsdvd/title=TITLE
/lsdvd/vmg_id=DVDVIDEO-VMG
/lsdvd/provider_id=PROVIDER
/lsdvd/track/ix=1
/lsdvd/track/length=2874.667
/lsdvd/track/vts_id=DVDVIDEO-VTS
/lsdvd/track/chapter/ix=1
/lsdvd/track/chapter/length=299.934
/lsdvd/track/chapter/startcell=1
/lsdvd/track/chapter
/lsdvd/track/chapter/ix=2
/lsdvd/track/chapter/length=299.500
/lsdvd/track/chapter/startcell=2
/lsdvd/track/chapter
/lsdvd/track/chapter/ix=3
/lsdvd/track/chapter/length=300.000
/lsdvd/track/chapter/startcell=3
[...]
/lsdvd/track/chapter/ix=11
/lsdvd/track/chapter/length=176.734
/lsdvd/track/chapter/startcell=11
/lsdvd/longest_track=1
Это НАМНОГО легче обрабатывать в сценарии, чем -удобочитаемый для человека вывод по умолчанию lsdvd
. например. если бы я хотел только длину глав в секундах:
$ lsdvd -c -Ox /path/to/some/dvd.iso' | xml2 | \
awk -F'[/=]' '$5 == "length" { print $6 }'
299.934
299.500
300.000
299.500
300.000
299.500
299.500
300.000
299.500
0.500
176.734
Я также отмечу, что если вы используете awk, вам не нужен grep. Таким образом, если вы хотите использовать удобочитаемый вывод -, ваш grep | grep | awk
(, а также len=${len:0:12}
для удаления замыкающей запятой )можно сократить до:
lsdvd -c VIDEO_TS | awk -F' +|,' '/Chapter:/ && /Length:/ { print $5 }' | \
while read len
Разделитель полей определяется здесь как один -или -пробелов ИЛИ запятая.
$ lsdvd -c '/path/to/some/dvd.iso' | \
awk -F' +|,' '/Chapter:/ && /Length:/ { print $5 }'
00:04:59.934
00:04:59.500
00:05:00.000
00:04:59.500
00:05:00.000
00:04:59.500
00:04:59.500
00:05:00.000
00:04:59.500
00:00:00.500
00:02:56.734
Вы можете использовать pstree
. Во-первых, получите PID процесса (, вы должны увидеть его в iotop
), а затем вы можете запустить:
$ pstree -p 2346372
rsync(2346372)───rsync(2346373)───rsync(2346374)
Это дает дерево процесса с PID 2346374
. Числа в скобках — это PID различных процессов в дереве.