Получите общую продолжительность видеофайлов в каталоге

Не делайте этого. rbash должен только использоваться в уже безопасной среде, если Вы не знаете то, что Вы делаете. Существует много способов вспыхнуть ограниченная оболочка удара, которые не легко предсказать заранее.

Функции могут легко быть переопределены просто путем выполнения command bash или command sh.

Что касается Ваших вопросов:

  • Вы не можете определить несколько функций одновременно непосредственно. Необходимо было бы сделать что-то вроде этого:
x()  { foo; }
alias f1=x
alias f2=x
  • rbash работы, потому что bash проверяет значение argv[0] на запуске. Если базовое имя, с продвижением разделенных тире, равно RESTRICTED_SHELL_NAME (принимающий значение по умолчанию к rbash, посмотрите config.h), это работает в ограниченном режиме. Это - тот же способ, которым это работает в режиме соответствия POSIX, если вызвано как sh. Вы видите это в следующем коде от shell.c в ударе 4.2, строки 1132-1147:
/* Return 1 if the shell should be a restricted one based on NAME or the
   value of `restricted'.  Don't actually do anything, just return a
   boolean value. */
int
shell_is_restricted (name)
     char *name;
{
  char *temp;

  if (restricted)
    return 1;
  temp = base_pathname (name);
  if (*temp == '-')
    temp++;
  return (STREQ (temp, RESTRICTED_SHELL_NAME));
}
30
02.12.2014, 08:50
10 ответов

У меня нет никакого .ts здесь, но это работает на .mp4. Использовать ffprobe (часть ffmpeg) для получения времени в секундах, например:

ffprobe -v quiet -of csv=p=0 -show_entries format=duration Inception.mp4 
275.690000

так для всего файлы .mp4 в текущем dir:

find . -maxdepth 1 -iname '*.mp4' -exec ffprobe -v quiet -of csv=p=0 -show_entries format=duration {} \;
149.233333
130.146667
275.690000

затем использование вставка к передают вывод до н.э и получают общее время в секундах:

find . -maxdepth 1 -iname '*.mp4' -exec ffprobe -v quiet -of csv=p=0 -show_entries format=duration {} \; | paste -sd+ -| bc
555.070000

Так, для .ts файлы вы могли попробовать:

find . -maxdepth 1 -iname '*.ts' -exec ffprobe -v quiet -of csv=p=0 -show_entries format=duration {} \; | paste -sd+ -| bc

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

exiftool -S -n Inception.mp4 | grep ^Duration
Duration: 275.69
exiftool -q -p '$Duration#' Inception.mp4
275.69

Общая длина для всего файлы .mp4 в текущем каталоге:

exiftool -S -n ./*.mp4 | awk '/^Duration/ {print $2}' | paste -sd+ -| bc
555.070000000000
exiftool -q -p '$Duration#' ./*.mp4 | awk '{sum += $0}; END{print sum}'
555.070000000000

Вы могли также передать вывод по каналу к другой команде, чтобы преобразовать общее количество в DD:HH:MM:SS, видеть ответы здесь .

Или использование exiftool, внутренний ConvertDuration для того (вам нужна относительно последняя версия хотя):

exiftool -n -q -p '${Duration;our $sum;$_=ConvertDuration($sum+=$_)
                    }' ./*.mp4| tail -n1
0:09:15
57
27.01.2020, 19:38

Исторически дерево каталогов /etc/rc.d обозначает систему Init, которая следует традиции инициализации системы 4.4 BSD, которую обычно называют системой rc init. Все современные (Free/Open/Net) системы BSD и Slackware Linux следуют этой традиции.

Дерево каталогов /etc/init.d обозначает систему инициализации System V (SysV), которая следует традиции инициализации системы AT & T UNIX, SunOS, Solaris. Это обычно называется системой SysV Init. Собственно Debian по-прежнему следует этой традиции в серии Wheezy, но планирует использовать SystemD в серии Jessie. Исторически RedHat и производные использовали SysV Init, но больше не использовали.

Также со временем в распределениях были приняты особенности обеих схем инициализации.

-121--28346-

Можно преобразовать имя файла в нечто, которое можно сравнить напрямую (например, временную метку Unix (количество секунд с начала эпохи) или YYYYMMDD , которая будет лексикографически сортируемой), а затем проверить, не старше ли она шести месяцев.

Например, сценарий типа (например, в /path/to/compare.sh ):

#! /bin/bash

LAST=$(date -d '6 months ago' +%s)

for FILE
do
    NAME=$(basename $FILE)
    DATE=$(perl -pe 's/(\d{2})(\d{2})(\d{4})/$3$2$1/' <<<$NAME)
    if (( $(date -d "$DATE" '+%s') < $LAST ))
    then
        rm -r $FILE
    fi
done

И сделать:

/path/to/compare.sh /var/app/backup/*

Здесь я преобразую в число секунд. Мне пришлось изменить DDMMYYY на YYYYMMDD , так как моя дата не приняла первую в качестве действительной даты. Преобразование в секунды является избыточным из-за этого, но я не уверен, почему date отклоняет первое (возможно, языковая проблема?).

-121--167030-
$ find -iname '*.ts' -print0 |\
xargs -0  mplayer -vo dummy -ao dummy -identify 2>/dev/null |\
perl -nle '/ID_LENGTH=([0-9\.]+)/ && ($t += $1) && printf "%02d:%02d:%02d:%02d\n",$t/86400,$t/3600%24,$t/60%60,$t%60'

Убедитесь, что установлен MPlayer .

0
27.01.2020, 19:38

Рационализация @jmunsch's answer, и используя paste, я только что узнал из @slm's answer, вы можете получить нечто подобное:

for i in *.ts; do LC_ALL=C ffmpeg -i "$i" 2>&1 | \
awk -F: '/Duration:/{print $2*3600+$3*60+$4}'; done | paste -sd+ | bc

Как и jmunsch, я использую ffmpeg для печати длительности, игнорируя ошибку о пропущенном выходном файле и вместо этого ищу в строке длительности выводимый результат ошибки. Я вызываю ffmpeg со всеми аспектами локали, вынужденными к стандартной C-локации, так что мне не придется беспокоиться о локализованных выходных сообщениях.

Далее я использую одну awk вместо его grep | grep | head | tr | awk. Этот вызов awk ищет (надеюсь, уникальную) строку, содержащую длительность:. Используя двоеточие в качестве разделителя, эта метка является полем 1, часы - полем 2, минуты - полем 3 и секунды - полем 4. Трейлинговая запятая после секунд, кажется, не беспокоит мою awk, но если у кого-то там есть проблемы, он может включить tr -d , в линию между ffmpeg и awk.

Теперь часть идет из шлма: Я использую вставку для замены новых линий на плюс знаки, но без влияния на новую линию (в отличие от tr \\n + у меня в была предыдущая версия этого ответа). Это дает суммарное выражение, которое может быть передано в bc.

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

TZ=UTC+0 date +'%j %T.%N' --date=@$(for i in *.ts; do LC_ALL=C \
ffmpeg -i "$i" 2>&1 | awk -F: '/Duration:/{print $2*3600+$3*60+$4}'; done \
| paste -sd+ | bc) | awk '{print $1-1 "d",$2}' | sed 's/[.0]*$//'

Часть внутри $(...) точно такая же, как и раньше. Используя символ @ в качестве индикатора, мы используем его как количество секунд с 1 января 1970 года. Полученная "дата" форматируется как день года, время и наносекунды. Из этого дня года вычитаем один, так как ввод нуля секунд уже приводит к 1-му дню 1970 года. Не думаю, что есть способ получить счет дня года, начинающегося с нуля.

Последний sed избавляет от лишних следящих нулей. Настройка TZ должна, надеюсь, заставить использовать UTC, чтобы летнее время не мешало действительно большим видеоколлекциям. Если у вас есть видеозаписи на срок более одного года, то этот подход все равно не сработает.

4
27.01.2020, 19:38

Использует ffmpeg и распечатывает тайм-аут в считанные секунды:

times=()
for f in *.ts; do
    _t=$(ffmpeg -i "$f" 2>&1 | grep "Duration" | grep -o " [0-9:.]*, " | head -n1 | tr ',' ' ' | awk -F: '{ print ($1 * 3600) + ($2 * 60) + $3 }')
    times+=("$_t")
done
echo "${times[@]}" | sed 's/ /+/g' | bc

Explanation:

for f в *.ts; do iterates каждый из файлов, заканчивающийся на ".ts"

ffmpeg -i "$f" 2>&1 перенаправляет вывод на stderr

grep "Duration" | grep -o" [0-9:. ]*, " голова | -n1 | tr '," ' '] изолирует время

awk -F: '{ вывод ($1 * 3600) + ($2 * 60) + $3 }' Преобразует время в секунды

times+=("$_t") добавляет секунды к массиву

echo "${times[@]}". | sed 's/ /+/g' | bc расширяет каждый из аргументов и заменяет пробелы и передает их в bc обычный калькулятор linux

.
6
27.01.2020, 19:38

Я не знаком с расширением .ts, но предполагая, что это какой-то тип видеофайла, вы можете использовать ffmpeg для определения длительности файла следующим образом:

$ ffmpeg -i some.mp4 2>&1 | grep Dura
  Duration: 00:23:17.01, start: 0.000000, bitrate: 504 kb/s

Затем мы можем разделить этот вывод, выбрав только длительность.

$ ffmpeg -i some.mp4 2>&1 | grep -oP "(?<=Duration: ).*(?=, start.*)"
00:23:17.01

Так что теперь нам нужен только способ итерации по нашим файлам и сбора этих значений продолжительности.

$ for i in *.mp4; do
    ffmpeg -i "$i" 2>&1 | grep -oP "(?<=Duration: ).*(?=, start.*)"; done
00:23:17.01
00:23:17.01
00:23:17.01

ПРИМЕЧАНИЕ: В данном примере я просто скопировал свой файл-пример some.mp4 и назвал его 1.mp4, 2.mp4, и 3.mp4.

Преобразование времени в секунды

Следующий фрагмент возьмет длительность сверху и преобразует ее в секунды.

$ for i in *.mp4; do 
    dur=$(ffmpeg -i "$i" 2>&1 | grep -oP "(?<=Duration: ).*(?=, start.*)");
    date -ud "1970/01/01 $dur" +%s; done
1397
1397
1397

Это берёт наши длительности и помещает их в переменную, $dur, по мере того, как мы перебираем файлы. Команда date затем используется для вычисления количества секунд синусоидальной эпохи Unix (1970/01/01). Вот вышеприведенная команда date разбита так, чтобы было проще увидеть:

$ date -ud "1970/01/01 00:23:17.01" +%s
1397

NOTE: Использование date таким образом будет работать только в том случае, если все ваши файлы имеют продолжительность < 24 часа (т.е. 86400 секунд). Если вам нужно что-то, что может обработать большую длительность, вы можете использовать это в качестве альтернативы:

sed 's/^/((/; s/:/)*60+/g' | bc
Пример
$ echo 44:29:36.01 | sed 's/^/((/; s/:/)*60+/g' | bc
160176.01

Подсчет времени

Затем мы можем взять вывод нашего цикла для и выполнить его в команде paste, которая будет включать знаки + между каждым номером, например, таким образом:

$ for i in *.mp4; do 
    dur=$(ffmpeg -i "$i" 2>&1 | grep -oP "(?<=Duration: ).*(?=, start.*)");
    date -ud "1970/01/01 $dur" +%s; done | paste -s -d+
1397+1397+1397

Наконец, мы запускаем эту команду в калькулятор командной строки, bc, чтобы просуммировать их:

$ for i in *.mp4; do 
    dur=$(ffmpeg -i "$i" 2>&1 | grep -oP "(?<=Duration: ).*(?=, start.*)");
    date -ud "1970/01/01 $dur" +%s; done | paste -s -d+ | bc
4191

В результате получим общую длительность всех файлов, в секундах. Разумеется, при необходимости это можно преобразовать в какой-нибудь другой формат.

3
27.01.2020, 19:38

Поскольку ubuntu поставляет libav вместо ffmpeg :

#!/bin/sh
for f in *.mp4; do
    avprobe -v quiet -show_format_entry duration "$f"
done | paste -sd+ | bc

В значительной степени основано на идеях MvG

0
27.01.2020, 19:38

Исходя из принятого ответа и используя классический инструмент UNIX reverse-polish:

{ find . -maxdepth 2 -iname '*.mp4' -exec ffprobe -v quiet -of csv=p=0 \
         -show_entries format=duration {} \; ; printf '+\n60\n*\np'; } | dc

783.493000

Т.е.: сложение + и p, затем вставка этого в dc и вы получите свою сумму.

1
27.01.2020, 19:38

Что ж, над всем этим решением нужно немного поработать, то, что я сделал, было очень просто, 1)

  1. зашел в нужную папку и щелкнул правой кнопкой мыши -> открыть другим приложение

  2. Затем выберите медиаплеер VLC,

  3. при этом начнется воспроизведение одного из видео, но затем

  4. нажмитеctrl + L , и вы увидите список воспроизведения видео, а где-то в левом верхнем углу вы увидите общую продолжительность

вот пример

1.List item

2.enter image description here

3.enter image description here

Вы можете видеть прямо под панелью инструментов, там написано Playlist[10 :35 :51] , поэтому папка содержит 10 часов 35 минут и 51 секунду общей продолжительности видео

2
27.01.2020, 19:38

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

find. -iname '*.mp4' -print0 | xargs --null exiftool -n -q -p '${Duration;our $sum;$_=ConvertDuration($sum+=$_)}' | tail -n1

0
27.01.2020, 19:38

Для музыкальных коллекций я использую Banshee [AUR].

enter image description here

0
05.11.2020, 13:16

Теги

Похожие вопросы