จะเก็บไฟล์รูปภาพในตัวแปร bash ได้อย่างไร?


14

หลังจากที่ฉันใช้คำสั่งต่อไปนี้

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

ฉันไม่สามารถเปิด tmp.png เป็นไฟล์ PNG ได้ ข้อมูลบางอย่างอาจหายไปเมื่อฉันใช้$pngStringเพื่อจัดเก็บไฟล์ภาพ

ดังนั้นคำถามคือฉันจะเก็บข้อมูลภาพทั้งหมดโดยใช้ตัวแปรในสคริปต์ทุบตีได้อย่างไร


คำสั่ง cat ทำงานได้ดี (เพื่อเก็บข้อมูลภาพในตัวแปร) เพียงลบเครื่องหมายคำพูดคู่ คำถามคือสิ่งที่คุณต้องการทำกับข้อมูลนี้หลังจากบันทึกไว้ในตัวแปรหรือไม่
coffeMug

5
catและechoทั้งหมดของตระกูลอยู่ที่ยูทิลิตี้ข้อความหัวใจ การปล่อยให้พวกเขาคลายความไม่มั่นใจในไฟล์ไบนารีจะมีผลลัพธ์ที่ไม่สามารถคาดการณ์ได้ นั่นเป็นเหตุผลที่สิ่งต่าง ๆ เช่นbase64ถูกคิดค้น
Shadur

ทำไมคุณถึงอยากให้มันเป็นตัวแปร? โดยทั่วไปแล้วตัวแปรของเชลล์มีจุดประสงค์เพื่อเก็บข้อความจำนวนเล็กน้อยไม่ใช่ข้อมูลไบนารีจำนวนมาก เชลล์ทั่วไปไม่สามารถรับมือกับข้อมูลไบนารี่ในตัวแปร (พวกมันสำลักเป็นไบต์ว่าง) ยกเว้น zsh
Gilles 'หยุดความชั่วร้าย'

ทำไมไม่เพียงcat example.png > tmp.pngหรือยังดีกว่าcp example.png tmp.png?
Wildcard

@Shadur catไม่ได้เป็นยูทิลิตี้ข้อความจริงๆ มันเป็นแทนคำสั่ง (ซึ่งแถบบรรทัดใหม่ต่อท้าย) การกำหนดตัวแปร (ซึ่งไม่สามารถมี null ไบต์) และechoคำสั่ง (ซึ่งอาจตีความลำดับทับขวา) catซึ่งจะทำให้เสียไบนารีไม่ แต่ฉันเห็นด้วยกับประเด็นโดยรวมของคุณ
Wildcard

คำตอบ:


20

คุณพูดถูกechoและ บริษัท ดูเหมือนจะจัดการเลขฐานสองไม่ได้ ฉันสงสัยว่าตัวละคร null จะหยุดสตรีมทั้งหมดเร็วเกินไป

คุณสามารถแปลงข้อมูลรูปภาพในรูปแบบ ASCII บางรูปแบบ ตัวอย่างเช่นนี่คือbase64:

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

3
ในระบบทุบตีของฉันฉันต้องใส่ตัวแปรในเครื่องหมายคำพูดอาจเป็นเพราะ base64 สามารถมี white space ได้: echo "$pic" | base64 --decode > pic2.jpeg
OldTimer

1

ปัญหาคือไบต์ที่เป็นโมฆะไม่สามารถส่งผ่านอาร์กิวเมนต์บรรทัดคำสั่งเนื่องจากมีการใช้ภายในเป็นตัวยุติอาร์กิวเมนต์ ไบต์อื่นทั้งหมดดูเหมือนจะใช้ได้ ดังนั้นโดยทั่วไปแล้วพื้นที่ทางเลือกที่มีประสิทธิภาพ (โดยทั่วไป) ค่อนข้างมากสำหรับการใช้base64คือการหลีกเลี่ยง null ไบต์และจากนั้นใช้printfในการแปลงข้อมูลเป็นรูปแบบเดิม:

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

\และ%ตัวอักษรพิเศษเพื่อprintfดังนั้นพวกเขาจะต้องหนีออกมามากเกินไป

โปรดทราบว่าหากข้อมูลอินพุตลงท้ายด้วยการขึ้นบรรทัดใหม่มันจะถูกปล้นโดยการทดแทนคำสั่ง นั่นไม่ควรเป็นปัญหาสำหรับ PNG โดยเฉพาะอย่างยิ่งเนื่องจากไบต์สุดท้ายใน PNG ที่ถูกต้องควรเป็น 0x82 ไบต์ที่มีนัยสำคัญน้อยที่สุดในIENDผลรวมซีอาร์ซีของก้อนอันว่างเปล่า


1
หากคุณต้องการแบ็กสแลชมากขึ้นให้ใช้: sed s/\\\\/\\\\\\\\/g\;s/%/%%/g\;s/\\x00/\\\\x00/g
Karel Vlk
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.