質問: ``` $ ls hoge.text fuga.text piyo.text all.text $ cat hoge.text hoge $ cat fuga.text fuga $ cat piyo.text piyo $ cat all.text hoge fuga piyo $ echo hoge >> hoge.text $ cat all.text hoge hoge fuga piyo ``` こういうことって可能ですか?
回答: 質問の例ですとファイルを使っているのは`cat`コマンドのみですね。 この様に、一度に一つのプロセスがファイル先頭から順に最後まで読む、という前提でしたら別のプロセスの出力を読ませる事で実現できます。 (前提なしで、きちんと通常のファイルとして振る舞わせるには fuse などで複数ファイルをバックエンドにしたファイルを作れるファイルシステムを作るしか無いと思います) ### 名前付きパイプを使う方法 まず、名前付きパイプのファイルを作ります。 ``` mkfifo all.txt ``` そして、ファイルを連結して出力するプロセスをバックグラウンドで起動します。今回は`cat`を使う事にします。 ``` cat hoge.txt fuga.txt piyo.txt >all.txt & ``` この状態で all.txt を読むと、上記の出力用のプロセスから受けとる事になります。 (まぎらわしいので、読む側のコマンドには**以後 `nl` を使います**) ``` nl all.txt #以下出力 1 hoge 2 fuga 3 piyo ``` 最後まで読むと、出力用のプロセスは終了しますから、もう一度読もうとすると all.txt への入力を待機した状態でストップする事になります。 例えば下記の様に、出力用のプロセスを繰り返し実行するようにすると、何度でも読めることになります。 ``` while true; do cat hoge.txt fuga.txt piyo.txt >all.txt; done & ``` ### Bash のプロセス置換を使う方法 Bash には名前付きパイプを使う方法と同じ様な事を、自動でやってくれる機能があります。 ただ、この方法ではファイル名は指定できないので、all.txt でなければならない場合は使えません。 Bash のコマンド行では `<(コマンド)` という表記はファイル名に置き換えられます。 ``` ls <(echo hello) # 手元の環境での出力: /dev/fd/63 # ファイル・ディスクリプターを使っている様です # 環境によっては名前付きパイプを使うらしいです ``` このファイルは bash が用意した物で、コマンド行で実行されたメインのプロセス(上記の例ですと`ls`)が読む場合のみ有効です。 `<()` の中で指定されたコマンドの出力がつなげられています。 質問の例ですと下記の様に実行すればよいです。 ``` nl <(cat hoge.txt fuga.txt piyo.txt) # 以下出力 1 hoge 2 fuga 3 piyo ```