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.