Linux: Как вывести список всех видеофайлов с разрешением ровно 720p?

У меня есть несколько видео файлов с разными разрешениями. Теперь я хочу перечислить только имена файлов видео, например, с разрешением 720p. Я предпочитаю один вкладыш в командной строке bash, и я могу получить полезную информацию о видео, включая разрешение, когда я выполняю:

avconv -i video.mp4

но эта комбинация:

find -exec sh -c 'if [[ "$(avconv -i {}") == *720* ]] ; then echo 720 found; fi;'

выдает ошибку: exec - отсутствует аргумент.

Честно говоря, я почти не борюсь со структурами команд bash, особенно с комбинированными командами. Итак, что не так в моей комбинированной командной строке?

Спасибо.

4 ответа

Может быть, эта команда включает в себя то, что вы ищете:

for i in *.mp4; do if [[ $(avconv -i $i) =~ .*720.* ]]; then echo $i; fi; done

Это может быть удивительно, но -exec может быть использован в качестве теста в find вызов:

find -type f -exec sh -c 'ffprobe -show_streams 2>/dev/null "$1" | grep -q coded_height=720' sh {} \; -print

Приведенная выше команда перейдет в подкаталоги. Для поиска в текущем каталоге используйте только -maxdepth 1 т.е.

find -maxdepth 1 -type f -exec …

Обратите внимание, что ffprobe проверим все файлы. Очевидно, что это не удастся для не-медиа файлов, но вы можете получить не видео-медиа (например, .jpg) в окончательном выводе. Чтобы избежать этого, некоторые дополнительные тесты в find следует использовать до -exec Например:

find -maxdepth 1 -type f \( -iname "*.avi" -o -iname "*.mp4" -o -iname "*.mkv" \) -exec sh -c 'ffprobe -show_streams 2>/dev/null "$1" | grep -q coded_height=720' sh {} \; -print

Или лучше вы можете проверить тип пантомимы с file:

find -maxdepth 1 -exec sh -c 'file --mime-type "$1" | grep -q "video/"' sh {} \; -exec sh -c 'ffprobe -show_streams 2>/dev/null "$1" | grep -q coded_height=720' sh {} \; -print

Читать man find Узнать больше.


РЕДАКТИРОВАТЬ:

Эта команда (мис) использует avconv, как вы просили:

find -exec sh -c 'file --mime-type "$1" | grep -q "video/"' sh {} \; -exec sh -c 'avconv 2>&1 -i "$1" | grep -q "Stream.*x720"' sh {} \; -print

Проблема заключается в каждом вызове avconv в них выдает ошибку. Мы просто игнорируем это и извлекаем необходимую нам информацию. Это несколько уродливое решение. Я не совсем уверен, что ваш avconv ведет себя как мой, вам может потребоваться заменить Stream.*x720 с некоторым другим регулярным выражением.


что не так в моей комбинированной командной строке?

  • find -exec требует закрытия с \; или же +,
  • есть $( без ) после того, как вы отредактировали вопрос, есть "" чередующийся (не вложенный) с $(),
  • *720* может вызвать слипание оболочки, должно быть "*720*" (Я говорю о sh, а не внешняя оболочка),
  • выход avconv Вы пытаетесь разобрать идет к stderr Я думаю, вам нужно перенаправить его, прежде чем вы сможете разобрать его,
  • и может быть что-то еще.

Я не знаю avconv, обычно использую ffmpeg. Если вы установите его, вы можете использовать этот скрипт

      #!/bin/bash
OIFS="$IFS"
IFS=$'\n'

files=$(find ./ -type f -exec ls {} + | grep ".*\.mpg$\|.*\.avi$\|.*\.mkv$\|.*\.mp4$"| cut -c3-)

for f in ${files}
do
resolution=$(ffprobe -v error -select_streams v:0 -show_entries 
stream=height -of csv=s=x:p=0 ${f})
printf "%-100s %-10s\n" $f $resolution
done

На данный момент я нашел полезное решение:

 for i in ls *.m??; do sm=$(mediainfo $i | grep Height | sed 's/  //g');if [[ "$sm" == *720* ]]; then printf "Video: %-s $i %-s $sm \n"; fi; done

Здесь я могу зациклить все м?? видеофайлы и напечатайте его имя, включая условие "720". Без части if я мог бы показать мне все видео и их разрешения.

Я решил это с помощью других ответов здесь.

Когда я пытаюсь объединить find и exec и часть do вышеупомянутого решения, я получаю только сообщения "E: File read error" как результат из mediainfo для каждой темы:

 find -exec mediainfo "{}" \; -exec bash -c 'sm=$(mediainfo ${} | grep 720) : ; echo $sm' \;

Как я уже сказал, конструкция 'if' работает (для реального каталога), но я постараюсь также запустить ее с find.

Другие вопросы по тегам