shell howto: salve vários arquivos de dados binários (jpg) em um arquivo com alguns dados adicionais e separe novamente

3

Eu tenho um sistema com poder de cálculo restrito (fritzbox) e funções (busybox) e uma webcam, capaz de fornecer arquivos JPG. Agora estou procurando um método (baseado no shell script) para fazer o download de arquivos JPG a cada 5 segundos, salvá-los (isso não é problema com wget ) e transmiti-los posteriormente através de um servidor web.

Eu configurei tudo, mas encontrei algum problema: Como o sistema está ficando muito lento com tantos arquivos JPG em uma pasta (mesmo se eu dividi-los em várias pastas) eu pensei em gravá-los em um único arquivo ( echo , cat , ...) e extrair -los mais tarde novamente ( sed , awk ).
Agora, os scripts de shell não estão realmente confortáveis lidando com dados binários, portanto os comandos "echo" e "cat" falham, pois não produzem arquivos jpg legíveis.

Eu faço o download do arquivo JPG com wget para um arquivo temporário ou para uma variável. No momento, eu então cat de cada novo JPG para um arquivo comum, separado por uma string única, por exemplo "--myboundary", que eu echo sem novas linhas.

Como posso agora extrair o único jpg deste arquivo comum que contém todos os JPGs? Eu tentei awk , mas consegui resultados ruins.

    
por user13816 30.12.2011 / 18:31

2 respostas

2

Se você puder começar de novo, use apenas tar . Tem um "modo de acréscimo" com a opção r :

$ ls t.tar
ls: cannot access t.tar: No such file or directory
$ tar rvf t.tar t.c
t.c
$ tar rvf t.tar t.cpp
t.cpp
$ tar tf t.tar
t.c
t.cpp

(Como você pode ver, o arquivo tar não precisa existir para usar o modo append, então deve ser muito fácil de usar para o seu caso.)

Se você não tem o privilégio de uma implementação completa do GNU tar, awk deve poder ordenar o arquivo mesclado com algo semelhante (retirado de este post do Stack Overflow):

awk -vRS="--myboundary" '{ print $0 > NR".jpg" }' yourfile

Isso criará arquivos chamados 1.jpg , 2.jpg , etc. Problema: ele adiciona um \n perdido no final do arquivo.
Supondo que você tenha truncate e stat em seu ambiente, você pode corrigir esses arquivos com:

truncate -s $(( $(stat -c %s 1.jpg) - 1 )) 1.jpg

Se você não tiver stat , precisará de algo mais para descobrir o nome do arquivo (a análise da saída de ls pode ser aceita nessa circunstância, já que você conhece os nomes dos arquivos são são). Se você não tiver truncate , poderá fazer o truque com dd ou possivelmente com head ou tail .
Ou você pode ignorar o \n à direita, é provável que as imagens sejam exibidas corretamente, independentemente.

Demo:

$ cp orig.1.png blob
$ echo -n "HELLOHELLO" >> blob 
$ cat orig.2.png >> blob 
$ ls -l
total 36
-rw-r--r-- 1 test test 14916 Dec 30 19:42 blob
-rw-r--r-- 1 test test  5735 Dec 30 19:41 orig.1.png
-rw-r--r-- 1 test test  9171 Dec 30 19:41 orig.2.png

$ awk -vRS="HELLOHELLO" '{print $0 > "new."NR".png"}' blob
$ ls -l
total 56
-rw-r--r-- 1 test test 14916 Dec 30 19:42 blob
-rw-r--r-- 1 test test  5736 Dec 30 19:43 new.1.png
-rw-r--r-- 1 test test  9172 Dec 30 19:43 new.2.png
-rw-r--r-- 1 test test  5735 Dec 30 19:41 orig.1.png
-rw-r--r-- 1 test test  9171 Dec 30 19:41 orig.2.png

$ for i in new* ; do truncate -s $(( $(stat -c %s $i) - 1 )) $i ; done
$ ls -l
total 56
-rw-r--r-- 1 test test 14916 Dec 30 19:42 blob
-rw-r--r-- 1 test test  5735 Dec 30 19:43 new.1.png
-rw-r--r-- 1 test test  9171 Dec 30 19:43 new.2.png
-rw-r--r-- 1 test test  5735 Dec 30 19:41 orig.1.png
-rw-r--r-- 1 test test  9171 Dec 30 19:41 orig.2.png
$ md5sum *.png
70718d7b9e717206b4a8455ea32b51ed  new.1.png
531099b9527f5fc2b623a3f724573ea9  new.2.png
70718d7b9e717206b4a8455ea32b51ed  orig.1.png
531099b9527f5fc2b623a3f724573ea9  orig.2.png
    
por 30.12.2011 / 19:00
1

Você está praticamente tentando reinventar o tar ou formatos de arquivamento semelhantes; Não espere fazer as coisas manualmente para ser mais fácil do que usar ferramentas existentes.

Se você insistir em um limite personalizado (o que é perigoso, já que esse limite pode aparecer naturalmente em um dos arquivos jpeg), faça-o iniciar e terminar com uma nova linha. Isso facilitará o processamento com awk .

Eu recomendo manter cada arquivo separado, mas limitando o número de arquivos por diretório a um número pequeno o suficiente para não causar um impacto no desempenho. Com um arquivo a cada 5 segundos, uma estrutura de aninhamento de dia / hora / minuto fornece uma ramificação máxima de 366/60/20, o que deve ser bom em desempenho.

Se você quiser usar arquivos, e devido à falta de um comando r no Busybox tar, você pode armazenar N arquivos no sistema de arquivos, periodicamente fazer um arquivamento com os arquivos existentes e limpar o slate. Por exemplo, para fazer um arquivo a cada 100 arquivos:

set -- *
if [ $# -gt 100 ]; then
  set ../archives/*.tar
  eval "last=\${$#}"
  last=${last%[!0-9]}; last=${last##[!0-9]}
  tar cf ../archives/$((last+1)).tar -- *
  rm -- *
fi
    
por 30.12.2011 / 23:37