複数の入力をGhostscriptにパイプ

複数の入力をGhostscriptにパイプ

私はGhostscriptを使用して2つのPDFファイル(URLからダウンロード)をマージする1行の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

私は2つの入力PDFがダウンロードを完了する前にGhostscriptコマンドが実行されていると思います。おそらくこれが起こるのを待つ方法があります。

ベストアンサー1

これはあなたが探している答えではありませんが、実用的な選択肢です。


まず、背景知識は次のとおりです。

すべてのパイプタイプには、Bashで使用することを含め、読者が見つけることができないという欠点があります<(command-list)。 GhostScriptが入力ファイルを見つける必要があるかどうか、またはメモリ内のファイル全体を読み取るかどうかはわかりませんが、通常、多くのファイル形式では、パイプベースの入力が遅いか、より多くのメモリを使用できます(検索機能がないため)。 )ファイル入力の代わりに。

(私は堅牢性に期待しているのでよくわかりません。私はスクリプトが最初に動作し(信頼できる結果を提供します)、2番目に軽くて高速であることを望みます。 。使用)。

/tmp多くの(ほとんど?)Linuxディストリビューションの中で、通常、Solaris(SunOS 4およびSolaris 2.1以降)、NetBSD(4.0以降)、FreeBSD(7.0以上)、DragonFly BSD、およびOpenBSD(5.5以降)バージョン)一時ファイルシステム、RAMベースのファイルシステムです。これらのシステムで一時ファイルを回避することは非生産的です(提供するアプリケーションが入力を欠点なくパイプを介してストリームとして処理できることを完全に知らない限り)。

一般的な反例(つまり、一時ファイルの代わりにパイプを使用したときに発生する現象)は、たとえばまたはを介した単純なsedフィルタリングまたは処理ですawk。 GhostScriptは確かに「単純なフィルタや処理プログラム」ではありません。

現在のすべてのオペレーティングシステムは、最近使用したファイルをリポジトリから書き込んで読み取るのではなく、メモリに保存するのに十分スマートです。 (彼らは救うこの一時ファイルの状況では、コンテンツはディスクに一度書き込まれますが、読み取られません。 )したがって、/tmpRAMベースではないファイルシステムでも、一時ファイルはメモリに残り、最大1回だけディスクに書き込まれます。つまり/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または他のシグナルでスクリプトを中断しても、シャットダウントラップはそれを自動的に処理するため、後でクリーンアップジョブを追加する必要はありません。

おすすめ記事