? 4 sendo adicionado ao nome do arquivo com este script Bash, por quê?

6

Eu tenho este script que extrai um quadro de muitos mp4 vídeos e os armazena como png

for i in *.mp4; do
    [ -f "$i" ] || break
    number=$(echo "$i" | grep -o -E '[0-9]+')
    name=frame"$number".png
    ffmpeg -i "$i" -ss 00:01:00.000 -vframes 1 "$name"
done

os vídeos são nomeados como video1.mp4 , video2.mp4 , etc. Como o loop tira vídeos fora de ordem, extraio o número do vídeo para gerar o nome do arquivo de saída.

Isso está funcionando muito bem, mas os nomes dos arquivos png são assim:

frame1?4.png , frame3?4.png , frame3?4.png ...

por que o ?4 ?

ah, vejo agora que o 4 vem do 4 no mp4. Como obtenho apenas o primeiro número?

    
por SpaceDog 02.02.2018 / 15:41

2 respostas

10

Esse ? é apenas um caractere de espaço reservado gerado por ls para representar o caractere de nova linha que você incorporou ao seu nome de arquivo.

echo foo3bar.mp4 | grep -Eo '[0-9]+'

produziria:

3
4

Como existem duas sequências de 1 ou mais dígitos decimais nesse nome de arquivo.

Em vez disso, você poderia fazer:

for file in *[0-9]*.mp4; do
  n=${file%.*} # remove the extension
  n=${n%"${n##*[0-9]}"} # remove anything after the last digit
  n=${n##*[!0-9]} # remove everything up to the last non-digit.

  ffmpeg...
done

O que extrairia a seqüência de dígitos decimais mais à direita no nome do arquivo removido de sua extensão e evitaria executar vários comandos para cada arquivo.

Observe que esse código usa apenas a sintaxe POSIX sh padrão, portanto, você não precisa do bash para executá-lo. Com bash ou outros shells iguais aksh93, se você souber que o nome da raiz do arquivo contém apenas uma seqüência de dígitos, você também pode usar:

n=${file%.*} # remove the extension
n=${n//[^0-9]} # remove all non-digit characters

Com recursos especiais de bash :

[[ $file =~ ([0-9]+).*\. ]] && n=${BASH_REMATCH[1]}

Extrairia a sequência de dígitos mais à esquerda no nome raiz.

com zsh :

n=${(SM)${file:r}##<->}
    
por 02.02.2018 / 15:52
1

Você identificou corretamente que 4 está vindo da extensão .mp4 no nome do arquivo. O ponto de interrogação é provavelmente ls exibindo a nova linha que grep -o insere entre cada correspondência (essa é uma das razões para não confiar nos nomes de arquivos que ls exibe, a propósito).

Para extrair o primeiro dígito, ou melhor, o último dígito antes da extensão .mp4 , você pode fazer

n=${i%.mp4}
number=${n##*[!0-9]}

Primeiro, retira a extensão do nome em i e, em seguida, retira todos os não numerais do início dessa.

    
por 02.02.2018 / 15:51

Tags