6月 12 2008
cd の出力を tee するには
スクリプトの出力を一行一行 “| tee” につなぐことがあります(”script”しろよという話はここでは置いておきます)。
ですが cd コマンドの行を機械的に “| tee” につないでしまうと、上手くいきません。
$ cd somedir 2>&1 | tee logfile
このコマンドは終了時に(somedirではなく)元のディレクトリに戻ってきます。 なぜかと言うと cd コマンドがサブシェルで実行されるため、サブシェル終了時にカレントディレクトリが戻ってしまうからですね。
パイプを使わなければサブシェルで実行されることもなく、想定どおりの動作をさせることができますが、 これとまったく同じ動作をパイプを使わずに行うのは、少なくとも bash では難しいです。
しかし、zsh でかつ “setopt multios” されているならば(デフォルト動作です)、こんな風にできます。
$ cd somedir >logfile >/dev/stdin 2>&1
2つ以上のファイルにリダイレクトすることができます。
また、あくまで tee を使うことにこだわるならば、
$ cd somedir > >(tee logfile) 2>&1
とすることもできます。受ける側のみをサブシェルにすることができます。
>(cmd....), <(cmd....), =(cmd....) はなかなか便利なので、 zsh を使うなら覚えておいて損はありません。
それぞれプロセスを非同期で実行し、>,<の場合はファイルディスクリプタを指すデバイスに置換されます。( echo <(ls) などとしてみると分かるかも )
=(cmd....) は同様ですが、デバイスではなくテンポラリファイルを指します。
$ cat file1 =(echo ------) file2
などと、ファイルを指定する場所に任意のコマンドを差し込むことができます。
man zshexpn の PROCESS SUBSTITUTION の項を参考に。
zsh やっぱスゲエ 、ということで。
