Talvez este comando complemente o que você está procurando:
for i in *.mp4; do if [[ $(avconv -i $i) =~ .*720.* ]]; then echo $i; fi; done
Eu tenho vários arquivos de vídeo com diferentes resoluções. Agora quero listar apenas os nomes dos arquivos de vídeo com, por exemplo, Resolução de 720p. Eu prefiro um forro na linha de comando do bash e posso receber informações de vídeo úteis, incluindo resolução, quando eu executo:
avconv -i video.mp4
mas essa combinação:
find -exec sh -c 'if [[ "$(avconv -i {}") == *720* ]] ; then echo 720 found; fi;'
produz o erro: exec - missing argument.
Eu sou honesto, eu dificilmente luto com estruturas de comando bash, especialmente comandos combinados. Então, o que está errado na minha string de comando combinada?
Obrigado.
Talvez este comando complemente o que você está procurando:
for i in *.mp4; do if [[ $(avconv -i $i) =~ .*720.* ]]; then echo $i; fi; done
No momento, encontrei uma solução utilizável:
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
Aqui eu posso fazer um loop em todos os m ?? arquivos de vídeo e imprimir seu nome, incluindo a condição "720". Sem a parte if eu poderia deixar mostrar todos os vídeos e suas resoluções.
Eu trabalhei nisso com a ajuda de outras respostas aqui.
Quando tento combinar find e exec e a parte do da solução acima, recebo apenas mensagens "E: File read error" como resultado de mediainfo para cada assunto:
find -exec mediainfo "{}" \; -exec bash -c 'sm=$(mediainfo ${} | grep 720) : ; echo $sm' \;
Como eu disse, a construção 'if' funciona (para o diretório atual), mas tentarei fazer com que ele seja executado também.
Pode ser surpreendente, mas -exec
pode ser usado como um teste em find
invocação:
find -type f -exec sh -c 'ffprobe -show_streams 2>/dev/null "$1" | grep -q coded_height=720' sh {} \; -print
O comando acima irá descer para os subdiretórios. Para pesquisar no diretório atual, use apenas -maxdepth 1
, por exemplo:
find -maxdepth 1 -type f -exec …
Observe que ffprobe
testará todos os arquivos. Obviamente falhará em arquivos que não sejam de mídia, mas você poderá obter uma mídia que não seja de vídeo (como .jpg
) na saída final. Para evitar isso, alguns testes adicionais em find
devem ser usados antes de -exec
, por exemplo:
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
Ou melhor, você pode testar o tipo MIME com 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
Leia man find
para saber mais.
Este comando (mis) usa avconv
, como você pediu:
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
O problema é que todas as invocações de avconv
emitem um erro. Nós simplesmente ignoramos e extraímos as informações de que precisamos. Esta é uma solução um tanto feia. Não tenho certeza se o seu avconv
se comporta como meu, talvez seja necessário substituir Stream.*x720
por outro regex.
what is wrong in my combined command string?
find -exec
requer fechamento com \;
ou +
, $(
sem )
""
intercalado (não aninhado) com $()
, *720*
pode acionar a globalização do shell, deve ser "*720*"
(estou falando de sh
, não do shell externo), avconv
que você tenta analisar vai para stderr
, acho que você precisa redirecioná-lo antes de poder analisá-lo, Tags command-line resolution video find linux