コンテンツを独立して保持しながら、プログラム間で複数のファイルのコンテンツを転送します。

コンテンツを独立して保持しながら、プログラム間で複数のファイルのコンテンツを転送します。

多くのファイルを読み込み、その出力を後続のプログラムにパイプし、同時に別のデータパイプラインとして保持したいと思います。

program1 *.txt | program2 | program3 folder

上記の構文が単一のデータストリームに対して何ができるかを知っていますが、タスク全体でファイルを別々に保持することを検討しています。上記は次のように翻訳されています。

  1. プログラム1はテキストファイルを読み取り、それをプログラム2にパイプします。
  2. プログラム2はデータを単独で処理し、それをプログラム3にパイプします。
  3. program3 は、元のファイルと同じ名前のフォルダ内のファイルにデータを書き込みます。

この種の作業は現在Gulpのようなビルドツールの領域ですが、シェルがそれを完全に置き換えることができるかどうかを確認しようとしています。プログラムは1つだけを処理するように書かれているので、stdinこれは実現可能には見えません。

複数のファイルを読み書きすることはプログラム自体内で処理されるので問題になりません。

次のことを調べましたが、正しい解決策ではないようです。

  • teeコマンド
  • ファイル記述子
  • 変える

1つの可能なアプローチは、個々のファイルごとにプロセスを作成し、どこかにファイル名のリストを保持することですが、私はよりエレガントなアプローチを望んでいます。

答え1

他のファイルと同様に、パイプはテキストストリーム(より正確にはバイトストリーム)です。 Unixの基本的なビルディングブロックは単純な傾向があります。プロセス間の相互作用は主に非定型データに基づいています。オペレーティングシステムは、ファイル名でラベル付けされた複数のストリームを持つ通信チャネルを提供しません。プログラムがこれを行う必要がある場合は、ストリームごとにパイプを1つずつ独自のパイプを配置する必要があるのが最も自然な実装です。

program2とが各ストリームに独立して適用される場合、program3そのコピーは各ファイルに対して実行されます。順番に実行するには、シェルループを使用します。パイプと同様に、ループはプログラムを相互に接続するシェル機能の1つです。出力をどこに置くかを知らせるために、program3一般的なインタフェースはprogram3標準出力に書き込み、出力をファイルに指定するためにシェルのリダイレクト構造を使用することです。シェルは、ファイル名を作成するためのいくつかの基本的な文字列操作構成を提供します。これは単なる接続です。

for x in *.txt; do
  program1 "$x" | program2 | program3 >"folder/$x"
done

プログラムがIO集約的であるがCPU集約的であり、複数のCPUがある場合は、並行して実行することをお勧めします。まったく新しいGNUツールを使えば使えます。xargsプログラムを並列に実行します。システムのCPU数をパラメータとして渡します-P。実行する必要があるコマンドはxargsパイプなので、シェルを呼び出すように作成する必要があります。

find -maxdepth 1 -name '*.txt' -print0 |
xargs -0 -n 1 -P 4 sh -c 'program1 "$1" | program2 | program3 >"$0/$1"' "folder"

あなたはそれを使用することができますGNUパラレルxargsの代わりにシステムのCPU数を自動的に決定します。

parallel sh -c 'program1 "$1" | program2 | program3 >"$0/$1"' "folder" ::: *.txt

単一のインスタンスが必要program2program3複数のファイルを処理する場合は、複数のパイプを入力として受け取るようにカスタムインターフェイスを使用してこれらのプログラムを設計する必要があります。これを行う標準的な方法はありません。 1つの方法は、入力を提供するプログラムを呼び出すことです。これは、出力を処理するためにどのプログラムを呼び出すかを知らせるxargsのと同じように機能します。parallel

答え2

言ってるよ

program1 file1.txt   | program2 | program3 > folder/file1.txt
program1 file2.txt   | program2 | program3 > folder/file2.txt
program1 file42.txt  | program2 | program3 > folder/file42.txt
program1 green.txt   | program2 | program3 > folder/green.txt
program1 indigo.txt  | program2 | program3 > folder/indigo.txt
program1 leopard.txt | program2 | program3 > folder/leopard.txt
program1 lion.txt    | program2 | program3 > folder/lion.txt
   ⋮        ⋮            ⋮          ⋮                 ⋮ 

あなたはこれを行うことができます

for f in file1.txt file2.txt file42.txt green.txt indigo.txt leopard.txt lion.txt ...
do
    program1 "$f" | program2 | program3 > folder/"$f"
done

現在のディレクトリ内のすべてのテキストファイルに対してこれを行うには、ワイルドカード(「globs」とも呼ばれます)を使用します。

for f in *.txt
do
    program1 "$f" | program2 | program3 > folder/"$f"
done

関連情報