stdin에서 오는 지정되지 않은 수의 Base64 인코딩 파일 스트림(Base64 인코딩 및 cat'ed 이미지 파일)의 파일 형식을 결정해야 합니다.
단일 파일은 ... | base64 -d | identify -
.
여러 파일의 문제는 스트림에 있는 각 파일의 EOF를 결정하는 것입니다. 파일을 stdout으로 보내기 전에 분리 하더라도 \004
파이프( identify
또는 file
등)의 수신 끝은 스트림에 여러 파일이 있다는 것을 인식하지 못하는 것 같습니다(예, 스트림이하나파일이지만 EOF 스트림이 "어떻게든" 다양한 값에 대해 작동하기를 원합니다.
표준입력을 통해 루프를 돌려보았 while read REPLY
으나 read
파일 기반이 아닌 라인 기반이어서 원하는 대로 동작하지 않는 것 같습니다.
[나중에 편집] 모두 400KB 미만인 파일이 3~10개 있으므로 크기와 처리는 내 사용 사례에서는 문제가 되지 않지만 일반적인 문제에는 관심이 있습니다.
[나중에] 저는 tmp 파일(현재 솔루션)을 사용하지 않으려고 노력하고 있습니다. 주로 프로세스 간 스트림이 더 효율적인 버퍼일 때 파일 시스템을 인접한 두 프로세스 간의 링크로 사용하는 것에 철학적으로 반대하기 때문입니다. . 이것이 거창하게 들린다는 것을 알고 있으므로 지금 작동해야 하는 솔루션을 위해 물론 tmp 파일을 사용합니다. 그러나 나는 내 지식에 공백이 있다는 것을 깨닫고 일반적인 경우에 대한 답을 찾기 위해 애쓰고 있습니다.
답변1
\004
보내기전에 파일을 분리해서 보내 도stdout
..
좋은 소식은 전송 프로세스를 수정할 수 있다는 것입니다. 내 솔루션은 다음과 같습니다.
for f in *.jpg; do echo S; base64 "$f"; echo ""; done |
# the above is just an example sending process
while read dummy; do
sed -u '/^$/q' | base64 -d | identify -
done
밝히다:
- 단일 "파일 블록"은 데이터를 전달하지 않는 소비 라인(이 경우 "S")으로 시작됩니다. 행을 찾을 수 없으면
read
전체 명령이 종료됩니다. sed
빈 줄이 나타날 때까지 데이터를 디코더에 전달합니다(참고: 추가 빈 줄은 출력을 변경하지 않습니다base64 -d
).sed
버퍼링되지 않은(-u
플래그)을 사용하는 것이 중요합니다. 그렇지 않으면sed
너무 많이 읽어서 너무 많은 데이터를 폐기하게 될 수 있으며, 그러면 다음 항목sed
(따라서 다음 항목identify
)이 필요한 모든 데이터를 얻지 못하게 됩니다.
힌트:
- 추가 줄은 파일 이름 등과 같은 "S" 이외의 메타데이터를 전달할 수 있습니다(그러나 이름 등의 줄 바꿈에 주의하세요).
- 생성된 출력이 입력보다 크므 로 양쪽에서 모두 사용하는
base64
것이 좋습니다 . 특히 스트림이 인터넷을 통해 전송되는 경우 더욱 그렇습니다.gzip
답변2
while read
입력을 파이프하고 구분 기호를 다음으로 설정하면 작동합니다 (백슬래시 이스케이프는 해석되지 않으므로 확장명 \004
사용 ).$'...'
read
for x in *.jpg ; do base64 < "$x" ; echo -e '\004'; done |
while read -rd $'\004' file ; do
echo "$file" | base64 -d | identify -
done
그러나 큰 파일의 경우에는 루프 내부의 내용을 파이프에서 읽을지 여부를 쉘이 알 수 없으므로 read
바이트 단위로 읽어야 하기 때문에 속도가 매우 느립니다. 버퍼링을 정확하게 제어할 수 있도록 이는 아마도 Perl이나 다른 실제 프로그래밍 언어로 구현되어야 합니다.