bash 변수에 이미지 파일을 저장하는 방법은 무엇입니까?


14

다음 명령을 사용한 후

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

tmp.png를 PNG 파일로 열 수 없습니다. $pngString이미지 파일을 저장하는 데 사용할 때 일부 정보가 손실 될 수 있습니다.

그래서 질문은 : bash 스크립트에서 변수를 사용하여 완전한 이미지 정보를 어떻게 저장할 수 있습니까?


cat 명령은 이미지 데이터를 변수에 저장하기 위해 정상적으로 작동합니다. 큰 따옴표 만 제거하십시오. 문제는 변수에 변수를 저장 한 후이 데이터로 무엇을하고 싶습니까?
coffeMug

5
cat그리고 echo모든 일리가 핵심 텍스트 유틸리티에 있습니다. 바이너리 파일에서 의심 할 여지없이 느슨하게하면 예기치 않은 결과가 발생합니다. 그것이 같은 base64것들이 발명 된 이유 입니다.
Shadur

왜 변수로 사용하고 싶습니까? 셸 변수는 일반적으로 대량의 이진 데이터가 아니라 소량의 텍스트를 저장하기위한 것입니다. 일반적인 쉘은 zsh를 제외하고 변수의 이진 데이터 (널 바이트에서 질식)에 대처할 수 없습니다.
Gilles 'SO- 악의를 멈춰라'

cat example.png > tmp.png아직 또는 더 나은가 cp example.png tmp.png?
와일드 카드

@Shadur cat는 실제로 텍스트 유틸리티가 아닙니다. 명령 대체 (후행 줄 바꿈), 변수 할당 (널 바이트를 포함 할 수 없음) 및 echo명령 (백 슬래시 시퀀스를 해석 할 수 있음)은 바이너리가 아닌 바이너리를 엉망으로 cat만듭니다. 그러나 나는 당신의 전반적인 요점에 동의합니다.
와일드 카드

답변:


20

당신은 옳고 echo& 회사는 바이너리를 잘 처리하지 못하는 것 같습니다. null 문자가 스트림을 너무 일찍 중단한다고 생각합니다.

그림 정보를 일부 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은 null 바이트를 이스케이프 한 다음 printf데이터를 원래 형식으로 변환하는 데 사용 하는 것입니다.

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

\%문자에 특별한 printf그들도 탈출 할 필요가 있도록.

또한 입력 데이터가 개행 문자로 끝나는 경우 명령 대체로 제거됩니다. 유효한 PNG의 마지막 바이트는 빈 IEND청크의 CRC 합계 에서 가장 중요하지 않은 바이트 인 0x82이어야하므로 PNG에는 특별히 문제가되지 않습니다 .


1
더 많은 백 슬래시를 원하면 다음을 사용하십시오. sed s/\\\\/\\\\\\\\/g\;s/%/%%/g\;s/\\x00/\\\\x00/g
Karel Vlk
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.