여러 입력을 Ghostscript로 파이프

여러 입력을 Ghostscript로 파이프

저는 Ghostscript를 사용하여 두 개의 PDF 파일(URL에서 다운로드)을 병합하는 한 줄 Linux 명령을 생성하려고 합니다. 하지만,임시 파일을 만들고 싶지 않습니다.(모든 것은 기억에서 이루어져야 합니다).

다음 명령이 작동하지 않는 것 같습니다(프로세스 대체를 통해 이를 달성하려고 했습니다).

gs -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=combined.pdf <(curl http://example.com/one.pdf) <(curl http://example.com/two.pdf)

이 명령을 실행하면 다음 오류가 발생합니다.

**** Warning:  An error occurred while reading an XREF table.
**** The file has been damaged.  This may have been caused
**** by a problem while converting or transfering the file.
**** Ghostscript will attempt to recover the data.
Error: /ioerror in --run--
Current allocation mode is local
Last OS error: Illegal seek
GPL Ghostscript 9.18: Unrecoverable error, exit code 1

나는 두 개의 입력 PDF가 다운로드를 완료하기 전에 Ghostscript 명령이 실행되고 있다고 생각합니다. 아마도 이것이 일어날 때까지 기다릴 방법이 있을 것입니다.

답변1

이는 귀하가 찾고 있는 답변은 아니지만 실용적인 대안입니다.


먼저, 배경지식은 다음과 같습니다.

모든 파이프 유형에는 Bash에서 사용하는 것을 포함하여 독자가 찾을 수 없는 단점이 있습니다 <(command-list). GhostScript가 입력 파일을 찾아야 하는지 아니면 메모리의 전체 파일을 읽는지 여부는 알 수 없지만 일반적으로 많은 파일 형식의 경우 파이프 기반 입력이 더 느리거나 더 많은 메모리를 사용할 수 있습니다(찾기 기능이 없기 때문에). ) 파일 입력 대신.

(나는 견고성에 기대고 있기 때문에 잘 모르겠습니다. 나는 내 스크립트가 먼저 작동하고(신뢰할 수 있는 결과 제공) 두 번째로 가볍고 빠르기를 원합니다. 임시 파일을 피한다고 해서 시스템의 속도가 빨라지거나 리소스 사용량이 줄어들지는 않습니다. 사용).

/tmp많은(대부분?) Linux 배포판 중에서 일반적 으로 Solaris(SunOS 4 및 Solaris 2.1 이후), NetBSD(4.0 이상), FreeBSD(7.0 이상), DragonFly BSD 및 OpenBSD(5.5 이상) 버전) 이임시 파일 시스템, RAM 기반 파일 시스템입니다. 이러한 시스템에서 임시 파일을 피하는 것은 비생산적입니다(제공하는 응용 프로그램이 입력을 단점 없이 파이프를 통해 스트림으로 처리할 수 있다는 것을 완전히 알지 않는 한).

일반적인 반례(즉, 임시 파일 대신 파이프를 사용할 때 발생하는 현상)는 sed예를 들어 또는 를 통한 간단한 필터링 또는 처리 입니다 awk. GhostScript는 확실히 "단순한 필터나 처리 프로그램"이 아닙니다.

현재의 모든 운영 체제는 최근에 사용한 파일을 저장소에서 쓰고 읽는 대신 메모리에 보관할 만큼 똑똑합니다. (그들은 대게구하다이 임시 파일 상황에서는 내용이 디스크에 한 번 기록되지만 다시 읽히지는 않습니다. ) 따라서 /tmpRAM 기반이 아닌 파일 시스템에서도 임시 파일은 메모리에 남아 최대 한 번만 디스크에 기록됩니다. 즉 /tmp, RAM 기반이 아닌 시스템에서도 임시 파일을 선택하는 것이 좋습니다.

전체적으로 위의 내용은 일반적인 사용 시 다음이 필요함을 의미합니다.아니요임시 파일은 피하는 것이 좋습니다. 특히 처리를 위해 변환기나 애플리케이션에 공급되는 경우에는 더욱 그렇습니다.

실제로 임시 파일을 피하려는 일반적인 이유는 다음과 같은 변형입니다.

나는 스크립트를 중단할 때 불필요한 임시 파일을 남겨두거나 오류로 인해 실패하거나 종료되거나 제대로 작동하지 않는 것을 원하지 않습니다.

Bash와 mktemp유틸리티를 사용하면 이러한 상황을 피하는 것이 쉽지 않습니다. 나는 몇 년 동안 다음 관용구를 사용해 왔습니다.

#!/bin/bash
Work=$(mktemp -d) || exit 1
trap "cd / ; rm -rf '$Work'" EXIT

/tmp/이렇게 하면 스크립트가 종료될 때 자동으로 삭제되는 임시 디렉터리(아래)가 생성됩니다 . (Linux coreutils는 mktemp이 디렉터리에 그룹이나 다른 사용자가 아닌 소유자 사용자만 액세스할 수 있도록 하므로 매우 안전합니다.)

bash 내장 기능은 (이러한 특정 인용문을 통해) 공식화되어 나중에 환경 변수를 변경하더라도 트랩이 트리거될 때가 아니라 변수가 설정될 때 확장되기 trap때문에 올바른(원래) 임시 디렉토리가 삭제됩니다 .Worktrap

위의 작업을 수행한 후 예를 들어 다음을 사용할 수 있습니다.

curl 'http://www.example.com/one.pdf' > "$Work/one.pdf" || exit 1
curl 'http://www.example.com/two.pdf' > "$Work/two.pdf" || exit 1

gs -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=combined.pdf "$Work/one.pdf" "$Work/two.pdf" || exit 1

Ctrl+ C나 다른 신호 로 스크립트를 중단하더라도 종료 트랩이 이를 자동으로 처리하므로 이 후에 정리 작업을 추가할 필요가 없습니다.

관련 정보