Eu estou tentando fazer um script para tirar várias séries de seqüências de imagens dentro de subdiretórios do diretório de trabalho atual e enviá-las por meio do ffmpeg para criar arquivos de vídeo no diretório de trabalho atual nomeado após os diretórios. É complicado pelo fato de os nomes das seqüências de imagens variarem, assim como o número inicial das seqüências, mas o problema real é que eu sou novo no bash scripting. Aqui está um exemplo dos arquivos:
directoryFirstRender01
renderOne0032.png
renderOne0033.png
renderOne0034.png
directoryFourthRender01
renderFour4253.png
renderFour4254.png
renderFour4255.png
directoryFifthRender01
renderFiveTwo1367.png
renderFiveTwo1368.png
renderFiveTwo1369.png
Aqui está um esboço do script que tem vários problemas que eu conheço e provavelmente muitos mais que eu não sei. A razão pela qual eu não sei quantos problemas tem é porque fiquei preso obtendo e analisando os nomes dos arquivos, e sem isso eu não posso testar o resto:
#!/bin/bash
for DIR in (ls -d */); do
1STFILE=(ls $dir/ | sort -n | head -1)
STARTNO=${1STFILE:(-8):4}
IMGSEQ=${1STFILE%????.*}
EXTEN=${1STFILE*.}
ffmpeg -start_number $STARTNO -i $IMGSEQ%04d.$EXTEN $DIR.mkv
done
Meus principais problemas atuais que eu conheço são:
- Eu não sei como obter o nome do arquivo apenas do primeiro arquivo nos diretórios.
ls dir/ | sort -n | head -1
funciona no terminal, mas não em um script.
- A extração de substring para obter o primeiro número do primeiro arquivo só funcionaria em sequências de imagens de 4 dígitos. Existe uma maneira de aceitar
renderSix00001.png-renderSix99999.png
e renderSeven001.png-renderSeven999.png
? Isso também é um problema com a linha recebendo $IMGSEQ
, e o %04d
na linha ffmpeg precisaria ser alterado de alguma forma.
- Acho que vou ter problemas com a variável
$IMGSEQ
misturando com o %04d
no nome do arquivo de entrada do ffmpeg, sem colchetes, mas ainda não cheguei tão longe. Qual sintaxe eu uso lá $IMGSEQ(%04d).$EXTEN
or $IMGSEQ {%04d}.$EXTEN
talvez? (Coisas como esta é porque é uma droga estar pulando no final do script)
- (problema menor: 1. Eu sei que usar
ls
em for DIR in (ls -d */)
é desaprovado, mas não sei como filtrar quaisquer arquivos no diretório de trabalho atual e apenas trabalhar nos diretórios.)
Tenho certeza de que o script parece uma bagunça completa. Qualquer orientação geral para que a coisa toda funcione seria muito bem-vinda, mas se ninguém tiver paciência para me acompanhar, se eu puder obter ajuda e analisar os nomes dos arquivos, talvez eu mesmo possa consertar o resto. Obrigado.
UPDATE 1: (Depois de aplicar as sugestões de Ron)
Obrigado mais uma vez, Ron! Este é o roteiro quase final:
#!/bin/bash
for DIR in $(ls -d */)
do
FIRSTFILE=$(ls $DIR | sort -n | head -1)
STARTNO=$(echo $FIRSTFILE | grep -Eo "[0-9]+")
DIGITNO=${#STARTNO}
IMGSEQ=${FIRSTFILE%????.*}
EXTEN=${FIRSTFILE#*.}
OUTPUT=${DIR%/}
ffmpeg -start_number $STARTNO -i "$DIR$IMGSEQ"%0"$DIGITNO"d".$EXTEN" $OUTPUT.mkv
done
Como, graças a Ron, a variável $STARTNO
aceitará agora comprimentos de vários dígitos, estou usando a expansão de parâmetro de comprimento na linha $DIGITNO
para obter o número a ser usado na parte %04d
para torná-lo %03d
ou %05d
, conforme necessário, para que funcionem também. Eu estou esperando que o uso liberal de "
para separar o %04d
das variáveis adjacentes não seja considerado uma forma ruim (se foi, qual é o caminho certo?). A única parte que falta no script (eu acho!) É como fazer com que $IMGSEQ
aceite comprimentos de vários dígitos. Eu não tenho idéias para isso agora. Se alguém souber, eu gostaria de saber, mas talvez eu possa encontrá-lo vasculhando a documentação de expansão de parâmetro, como se eu não tivesse mais do que suficiente para uma vida inteira. :)
UPDATE 2: (Sucesso!)
Descobri isso! (Como fazer com que o IMGSEQ aceite nomes que envolvam comprimentos de vários dígitos) Trabalhando com base na sugestão de Ron para $STARTNO
usando (echo $FIRSTFILE | grep -Eo "[0-9]+")
Eu criei
IMGSEQ=$(echo ${FIRSTFILE%.*} | grep -iEo "[a-z]+")
-
${FIRSTFILE%.*}
pega o primeiro arquivo e retira a extensão.
- grep é pesquisa de padrões
- A parte
-i
de -iEo
é para fazer com que o grep aceite correspondências de maiúsculas e minúsculas.
- A parte
-E
de -iEo
é para (citando de man grep
) "Interpretar PATTERN como uma expressão regular estendida". O que quer que isso signifique.
- A parte
-o
de -iEo
é apenas imprimir o padrão correspondente.
-
[a-z]
é para corresponder ao padrão de qualquer letra do alfabeto
-
+
diz ao grep que o padrão do alfabeto anterior deve ser correspondido "uma ou mais vezes" (faça isso várias vezes para obter todas as letras).
Uma limitação disso é que ele não iria lidar com nomes de arquivos com caracteres especiais como -
ou _
, mas eu posso viver com isso por enquanto.
Então aqui está o roteiro semi-final!
#!/bin/bash
for DIR in $(ls -d */)
do
FIRSTFILE=$(ls $DIR | sort -n | head -1)
STARTNO=$(echo $FIRSTFILE | grep -Eo "[0-9]+")
DIGITNO=${#STARTNO}
IMGSEQ=$(echo ${FIRSTFILE%.*} | grep -iEo "[a-z]+")
EXTEN=${FIRSTFILE#*.}
OUTPUT=${DIR%/}
ffmpeg -n -start_number $STARTNO -i "$DIR$IMGSEQ"%0"$DIGITNO"d".$EXTEN" $OUTPUT.mkv
done
Então, execute em um diretório com alguns diretórios nomeados como meus diretórios de exemplo acima (exceto que eu adicionei um com uma seqüência de imagens preenchida com mais de 4 zeros para ter certeza de que funcionou também), este script executará as seguintes linhas ffmpeg após o outro:
ffmpeg -n -start_number 0032 -i directoryFirstRender01/renderOne%04d.png directoryFirstRender01.mkv
ffmpeg -n -start_number 4253 -i directoryFourthRender01/renderFour%04d.png directoryFourthRender01.mkv
ffmpeg -n -start_number 01367 -i directoryFifthRender01/renderFiveTwo%05d.png directoryFifthRender01.mkv
Freakin 'perfeito! Muito obrigado novamente por sua ajuda Ron! Eu definitivamente não teria sido capaz de terminar sem sua ajuda.