Po użyciu następującego polecenia
pngString="$(cat example.png)"
echo -n "$pngString" > tmp.png
Nie mogę otworzyć pliku tmp.png jako pliku PNG. Być może niektóre informacje są tracone, gdy używam $pngString
do przechowywania pliku obrazu.
Pytanie brzmi: w jaki sposób mogę przechowywać pełne informacje o obrazie, używając zmiennej w skrypcie bash?
cat
iecho
wszystkie podobne są narzędziami tekstowymi . Pozbawienie ich niczego nie podejrzewających plików binarnych przyniesie nieprzewidziane skutki. Właśnie dlategobase64
wymyślono takie rzeczy .cat example.png > tmp.png
lub lepiejcp example.png tmp.png
?cat
tak naprawdę nie jest narzędziem tekstowym. To podstawienie polecenia (które usuwa końcowe znaki nowego wiersza), przypisanie zmiennej (która nie może zawierać bajtów pustych) iecho
polecenie (które może interpretować sekwencje odwrotnego ukośnika), które nie będą miały wpływu na układ binarnycat
. Ale zgadzam się z twoim ogólnym punktem.Odpowiedzi:
Masz rację, a
echo
firma nie radzi sobie z binarnością tak dobrze. Podejrzewam, że znaki zerowe zbyt wcześnie przerywają strumień.Możesz konwertować informacje o obrazie w pewnym formacie opartym na ASCII. Na przykład dotyczy to
base64
:źródło
echo "$pic" | base64 --decode > pic2.jpeg
Problem polega na tym, że bajty zerowe nie mogą być przekazywane przez argumenty wiersza poleceń, ponieważ są one wewnętrznie używane jako terminatory argumentów. Wszystkie pozostałe bajty wydają się być w porządku. Tak więc nieco bardziej wydajną przestrzennie (zazwyczaj) alternatywą jest użycie
base64
ucieczki przed pustymi bajtami, a następnie użycieprintf
do konwersji danych do oryginalnej postaci:\
I%
znaki mają specjalne doprintf
tak muszą być uciekł zbyt.Zauważ również, że jeśli dane wejściowe kończą się znakiem nowej linii, zostaną usunięte przez zastąpienie polecenia. Nie powinno to stanowić problemu szczególnie w przypadku plików PNG, ponieważ ostatni bajt w prawidłowym pliku PNG powinien mieć wartość 0x82, najmniej znaczący bajt w
IEND
sumie CRC pustej porcji.źródło
sed s/\\\\/\\\\\\\\/g\;s/%/%%/g\;s/\\x00/\\\\x00/g