受信側でパイプのように処理されるように(保存せずに)1つのストリームに複数のファイルを渡す方法は何ですか?

受信側でパイプのように処理されるように(保存せずに)1つのストリームに複数のファイルを渡す方法は何ですか?

stdinから来る、指定されていない数のBase64エンコーディングファイルストリーム(Base64エンコーディングおよびcat'edイメージファイル)のファイル形式を決定する必要があります。

単一のファイルは... | base64 -d | identify -

複数のファイルの問題は、ストリーム内の各ファイルのEOFを決定することです。ファイルをstdoutに送信する前に分離しても、\004パイプ(identifyまたはfileなど)の受信端は、ストリームに複数のファイルがあることを認識していないようです(ストリームが一つこれはファイルですが、EOFストリームは「どういうわけか」さまざまな値に対して機能したいと思います。

標準入力でループを回してみましたwhile read REPLYが、readファイルベースではなくラインベースなので、好きなように動作しないようです。

[後で編集]すべて400KB未満のファイルが3〜10個あるため、サイズと処理は私のユースケースでは問題になりませんが、一般的な問題には興味があります。

[後で]私はtmpファイル(現在のソリューション)を使用しないように努めています。主に、プロセス間ストリームがより効率的なバッファである場合、ファイルシステムを隣接する2つのプロセス間のリンクとして使用することに哲学的に反対するためです。 。これが途方もなく聞こえることがわかっているので、今動作する必要がある解決策にはもちろん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または他の実際のプログラミング言語で実装する必要があります。

関連情報