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または他の実際のプログラミング言語で実装する必要があります。