多くのファイルを読み込み、その出力を後続のプログラムにパイプし、同時に別のデータパイプラインとして保持したいと思います。
program1 *.txt | program2 | program3 folder
上記の構文が単一のデータストリームに対して何ができるかを知っていますが、タスク全体でファイルを別々に保持することを検討しています。上記は次のように翻訳されています。
- プログラム1はテキストファイルを読み取り、それをプログラム2にパイプします。
- プログラム2はデータを単独で処理し、それをプログラム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
単一のインスタンスが必要program2
でprogram3
複数のファイルを処理する場合は、複数のパイプを入力として受け取るようにカスタムインターフェイスを使用してこれらのプログラムを設計する必要があります。これを行う標準的な方法はありません。 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