Come archiviare un file immagine nella variabile bash?


14

Dopo aver usato il seguente comando,

pngString="$(cat example.png)"    
echo -n "$pngString" > tmp.png

Non riesco ad aprire tmp.png come file PNG. Forse alcune informazioni vanno perse quando uso $pngStringper archiviare il file di immagine.

Quindi la domanda è: come posso memorizzare le informazioni complete sull'immagine usando una variabile nello script bash?


Il comando cat funziona correttamente (per memorizzare i dati dell'immagine nella variabile). Basta rimuovere le doppie virgolette. La domanda è: cosa vuoi fare con questi dati dopo averli salvati nella variabile?
coffeMug

5
cate echotutti i suoi simili sono alla base delle utilità di testo . Lasciarli perdere inconsapevolmente su file binari avrà risultati imprevedibili. Ecco perché sono base64state inventate cose del genere .
Shadur,

Perché vuoi averlo come variabile? Le variabili shell sono in genere destinate a memorizzare piccole quantità di testo, non grandi quantità di dati binari. Nessuna delle solite shell è in grado di far fronte ai dati binari nelle variabili (si soffocano su byte null) tranne zsh.
Gilles 'SO- smetti di essere malvagio' il

Perché non solo cat example.png > tmp.pngo meglio ancora cp example.png tmp.png?
Wildcard

@Shadur, in catrealtà non è un'utilità di testo. È la sostituzione dei comandi (che rimuove le righe successive), l'assegnazione delle variabili (che non può contenere byte nulli) e il echocomando (che può interpretare le sequenze di barre rovesciate) che manterranno il binario, no cat. Ma sono d'accordo con il tuo punto complessivo.
Wildcard

Risposte:


20

Hai ragione in questo echoe la società non sembra gestire bene il binario. Sospetto che i caratteri null interrompano il flusso troppo presto.

È possibile convertire le informazioni sulle immagini in un formato basato su ASCII. Ad esempio, questo è con base64:

$ pic=`base64 pic.jpeg`
$ echo $pic | base64 --decode > pic2.jpeg
$ diff pic*
$ echo $?
0

3
Nel mio sistema bash ho dovuto racchiudere la variabile tra virgolette, probabilmente perché base64 può contenere spazi bianchi: echo "$pic" | base64 --decode > pic2.jpeg
OldTimer

1

Il problema è che i byte null non possono essere passati attraverso gli argomenti della riga di comando poiché vengono utilizzati internamente come terminatori di argomenti. Tutti gli altri byte sembrano andare bene. Quindi un'alternativa un po 'più efficiente in termini di spazio (in genere) all'utilizzo base64sarebbe quella di sfuggire ai byte null e quindi utilizzare printfper convertire i dati nella forma originale:

pngString="$(sed 's/\\/\\\\/g;s/%/%%/g;s/\x00/\\x00/g' <example.png)"
printf "$pngString" >tmp.png

I personaggi \e %sono speciali per printfcui devono essere sfuggiti anche loro.

Si noti inoltre che se i dati di input terminano con una nuova riga, verranno rimossi dalla sostituzione dei comandi. Questo non dovrebbe essere un problema specifico per i PNG poiché l'ultimo byte in un PNG valido dovrebbe essere 0x82, il byte meno significativo nella IENDsomma CRC del blocco vuoto .


1
Se vuoi ancora più barre rovesciate, usa: sed s/\\\\/\\\\\\\\/g\;s/%/%%/g\;s/\\x00/\\\\x00/g
Karel Vlk,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.