Làm thế nào để lưu trữ một tập tin hình ảnh trong biến bash?


14

Sau khi tôi sử dụng lệnh sau,

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

Tôi không thể mở tmp.png dưới dạng tệp PNG. Có thể một số thông tin bị mất khi tôi sử dụng $pngStringđể lưu trữ tệp hình ảnh.

Vì vậy, câu hỏi là: Làm thế nào tôi có thể lưu trữ thông tin hình ảnh hoàn chỉnh bằng cách sử dụng một biến trong tập lệnh bash?


Lệnh cat hoạt động tốt (để lưu trữ dữ liệu hình ảnh trong biến). Chỉ cần loại bỏ các dấu ngoặc kép. Câu hỏi là bạn muốn làm gì với dữ liệu này sau khi lưu chúng vào biến?
coffeMug

5
catechotất cả ilk của nó là tại các tiện ích văn bản trái tim . Để chúng lỏng lẻo không nghi ngờ trên các tệp nhị phân sẽ có kết quả không thể đoán trước. Đó là lý do tại sao những thứ như base64được phát minh.
Shadur

Tại sao bạn muốn có nó như một biến? Các biến Shell thường được dự định để lưu trữ một lượng nhỏ văn bản, chứ không phải một lượng lớn dữ liệu nhị phân. Không có trình bao thông thường nào có thể đối phó với dữ liệu nhị phân trong các biến (chúng bị sặc trên các byte rỗng) ngoại trừ zsh.
Gilles 'SO- ngừng trở nên xấu xa'

Tại sao không chỉ cat example.png > tmp.pnghoặc tốt hơn , cp example.png tmp.png?
tự đại diện

@Shadur, catkhông thực sự là một tiện ích văn bản. Đó là sự thay thế lệnh (loại bỏ các dòng mới), phép gán biến (không thể chứa byte rỗng) và echolệnh (có thể diễn giải các chuỗi dấu gạch chéo ngược) sẽ xáo trộn nhị phân, không cat. Nhưng tôi đồng ý với quan điểm chung của bạn.
tự đại diện

Câu trả lời:


20

Bạn đúng trong đó echo& công ty dường như không xử lý nhị phân tốt. Tôi nghi ngờ rằng các ký tự null phá vỡ luồng quá sớm.

Bạn có thể chuyển đổi thông tin hình ảnh theo một số định dạng dựa trên ASCII. Chẳng hạn, đây là với base64:

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

3
Trong hệ thống bash của tôi, tôi đã phải đặt biến trong dấu ngoặc kép, có lẽ vì base64 có thể chứa khoảng trắng: echo "$pic" | base64 --decode > pic2.jpeg
OldTimer

1

Vấn đề là các byte null không thể được truyền qua các đối số dòng lệnh vì chúng được sử dụng bên trong như các bộ kết thúc đối số. Tất cả các byte khác dường như là tốt. Vì vậy, một giải pháp thay thế hiệu quả hơn về mặt không gian (thông thường) để sử dụng base64sẽ là thoát các byte rỗng và sau đó sử dụng printfđể chuyển đổi dữ liệu về dạng ban đầu:

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

Các nhân vật \%đặc biệt là printfvì vậy họ cũng cần phải được trốn thoát.

Cũng lưu ý rằng nếu dữ liệu đầu vào kết thúc bằng một dòng mới, nó sẽ bị tước bằng cách thay thế lệnh. Đó không phải là vấn đề cụ thể đối với PNG vì byte cuối cùng trong PNG hợp lệ phải là 0x82, byte nhỏ nhất có ý nghĩa trong IENDtổng CRC của đoạn trống .


1
Nếu bạn muốn thêm dấu gạch chéo ngược, hãy sử dụng: sed s/\\\\/\\\\\\\\/g\;s/%/%%/g\;s/\\x00/\\\\x00/g
Karel Vlk
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.