Wie speichere ich eine Bilddatei in einer Bash-Variablen?

14

Nachdem ich den folgenden Befehl verwende,

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

Ich kann die Datei tmp.png nicht als PNG-Datei öffnen. Möglicherweise gehen beim $pngStringSpeichern der Bilddatei einige Informationen verloren .

Die Frage ist also: Wie kann ich die vollständigen Bildinformationen mit einer Variablen im Bash-Skript speichern?

Libin Wen
quelle
Der Befehl cat funktioniert einwandfrei (um die Bilddaten in der Variablen zu speichern). Entfernen Sie einfach die doppelten Anführungszeichen. Die Frage ist, was Sie mit diesen Daten machen möchten, nachdem Sie sie in der Variablen gespeichert haben.
coffeMug
5
catund echound alle seine ilk sind im Innersten Text - Utilities. Wenn Sie sie in Binärdateien ahnungslos verlieren, kann dies zu unvorhersehbaren Ergebnissen führen. Deshalb wurden solche Dinge base64erfunden.
Shadur
Warum möchten Sie es als Variable haben? Shell-Variablen sind normalerweise dazu gedacht, kleine Textmengen und keine großen Mengen von Binärdaten zu speichern. Keine der üblichen Shells kann mit Binärdaten in Variablen umgehen (sie verschlucken sich an Null-Bytes), außer zsh.
Gilles 'SO- hör auf böse zu sein'
Warum nicht einfach cat example.png > tmp.pngoder noch besser cp example.png tmp.png?
Wildcard
@ Shadur, catist nicht wirklich ein Textdienstprogramm . Es ist die Befehlsersetzung (die nachfolgende Zeilenumbrüche entfernt), die Variablenzuweisung (die keine Null-Bytes enthalten echodarf ) und der Befehl (der möglicherweise Backslash-Sequenzen interpretiert), der die Binärdatei kaputt macht, nicht cat. Aber ich stimme Ihrem allgemeinen Standpunkt zu.
Wildcard

Antworten:

20

Sie haben Recht damit echound die Firma scheint mit Binärdateien nicht so gut umzugehen. Ich vermute, dass die Nullzeichen den Stream zu früh unterbrechen.

Sie können Bildinformationen in ein ASCII-basiertes Format konvertieren. Zum Beispiel ist dies mit base64:

$ pic=`base64 pic.jpeg`
$ echo $pic | base64 --decode > pic2.jpeg
$ diff pic*
$ echo $?
0
unperson325680
quelle
3
In meinem Bash-System musste ich die Variable in Anführungszeichen setzen, wahrscheinlich, weil base64 Leerzeichen enthalten kann: echo "$pic" | base64 --decode > pic2.jpeg
OldTimer 31.12.13
1

Das Problem besteht darin, dass Nullbytes nicht über Befehlszeilenargumente übergeben werden können, da sie intern als Argumentterminatoren verwendet werden. Alle anderen Bytes scheinen in Ordnung zu sein. Eine etwas platzsparendere (normalerweise) Alternative zur Verwendung base64wäre es, die Null-Bytes zu umgehen und dann printfdie Daten in die ursprüngliche Form zu konvertieren:

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

Die \und %-Zeichen sind etwas Besonderes, printfdaher müssen sie auch maskiert werden.

Beachten Sie auch, dass die Eingabedaten, wenn sie mit einem Zeilenumbruch enden, durch die Befehlsersetzung entfernt werden. Dies sollte kein spezielles Problem für PNGs sein, da das letzte Byte in einem gültigen PNG 0x82 sein sollte, das niedrigstwertige Byte in der IENDCRC-Summe des leeren Chunks.

Karel Vlk
quelle
1
Wenn Sie noch mehr Backslashes wollen, verwenden Sie: sed s/\\\\/\\\\\\\\/g\;s/%/%%/g\;s/\\x00/\\\\x00/g
Karel Vlk