수신 측에서 파이프처럼 처리되도록(저장하지 않고) 하나의 스트림에 여러 파일을 전달하는 방법은 무엇입니까?

수신 측에서 파이프처럼 처리되도록(저장하지 않고) 하나의 스트림에 여러 파일을 전달하는 방법은 무엇입니까?

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이나 다른 실제 프로그래밍 언어로 구현되어야 합니다.

관련 정보