Як зберігати файл зображення у змінній bash?


14

Після використання наступної команди,

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

Не можу відкрити tmp.png як файл PNG. Можливо, деяка інформація втрачається, коли я використовую $pngStringдля зберігання файлу зображень.

Отже, питання полягає в тому, як я можу зберігати повну інформацію про зображення, використовуючи змінну в скрипті bash?


Команда cat працює чудово (для збереження даних про зображення у змінній). Просто видаліть подвійні лапки. Питання полягає в тому, що ви хочете зробити з цими даними після збереження їх у змінній?
coffeMug

5
catі echoвсі її помилки лежать в основі текстових утиліт. Якщо їх не пустить на бінарні файли, вони матимуть непередбачувані результати. Ось чому такі речі, як base64придумані.
Шадур

Чому ви хочете мати його як змінну? Змінні оболонки зазвичай призначені для зберігання невеликої кількості тексту, а не великої кількості двійкових даних. Жодна зі звичайних оболонок не може впоратися з бінарними даними в змінних (вони задихаються в нульових байтах), крім zsh.
Жил "ТАК - перестань бути злим"

Чому б не просто cat example.png > tmp.pngчи ще краще , cp example.png tmp.png?
Wildcard

@Shadur, catнасправді не є текстовою утилітою. Це заміна команд (яка позбавляє останніх рядків), призначення змінної (яка не може містити нульових байтів) і echoкоманда (яка може інтерпретувати послідовності зворотної косої риси), які будуть маніпулювати бінарними, а не cat. Але я згоден з вашою загальною точкою.
Wildcard

Відповіді:


20

Ви маєте рацію в тому, що echoкомпанія, схоже, не справляється з бінарними. Я підозрюю, що нульові символи занадто рано порушують потік.

Ви можете конвертувати інформацію про зображення у деякому форматі на основі ASCII. Наприклад, це з base64:

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

3
У моїй системі bash я повинен був укласти змінну в лапки, ймовірно, тому, що base64 може містити пробіл: echo "$pic" | base64 --decode > pic2.jpeg
OldTimer

1

Проблема полягає в тому, що нульові байти не можна передавати через аргументи командного рядка, оскільки вони внутрішньо використовуються як термінатори аргументів. Усі інші байти здаються нормальними. Отже, дещо більш ефективною (просто) альтернативою використання base64є уникнути нульових байтів, а потім використовувати printfдля перетворення даних у початковий вигляд:

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

\І %символи мають спеціальне значення, printfтому вони повинні бути екрановані теж.

Також зауважте, що якщо вхідні дані закінчуються новим рядком, вони будуть позбавлені підстановки команд. Це не повинно бути проблемою спеціально для PNG, оскільки останній байт у дійсному PNG повинен бути 0x82, найменш значущий байт у IENDсумі CRC порожнього фрагмента.


1
Якщо ви хочете ще більше нахилів, використовуйте: sed s/\\\\/\\\\\\\\/g\;s/%/%%/g\;s/\\x00/\\\\x00/g
Karel Vlk
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.