複数のコマンドを少ないコマンドにパイプ

複数のコマンドを少ないコマンドにパイプ

どうして

{$several_commands} | less

lessこれを複数のファイルとして扱い、ナビゲーションを有効にして:n有効にします:p

これは明確な説明ではない可能性があるため、例を挙げてみましょう。現在機能があります

svndiff () 
{ 
    for a in `svn status | \grep ^M | sed 's/M       //'`;
    do
        svn diff $a | less;
    done
}

目的は、明らかにless私が修正したすべてのファイルの違いを確認することです。ただし、この構文では、Q1つの「ファイル」を閉じ、次の「ファイル」を開くにはキーを使用する必要があります。 (次のファイル)と(前のファイル)lessコマンドを使用してファイル間を移動できるようにしたいです。どうすればいいですか?:n:p

答え1

プロセス置換を使用できます。

less -f <(svn diff this) <(svn diff that)

しかし、これはループで使用するのが難しいです。おそらく一時ファイルを使用する方が良いでしょう。

#!/bin/bash
dir=$(mktemp -d)
outfiles=()
IFS=$'\n'
set -f 
for file in $(svn status | \grep ^M | sed 's/M       //') ; do
    outfile=${file#.}             # remove leading dot (if any)
    outfile=${outfile//\//__}     # replace slashes (if any) with __
    svn diff "$file" > "$dir/$outfile";
    outfiles+=("$dir/$outfile")   # collect the filenames to an array
done
less "${outfiles[@]}"
rm -r "$dir"

上記のコードは、一時ファイル名にファイル名が表示されるようにし、スラッシュと先行点をいくつかクリーンアップします。 (このようなパスを得たら。ファイル名をどのように./foo/bar出力するのか覚えていませんが何…)svn

@Kusalanandaが言ったように、"$dir"/*この順序が重要でない場合はそうすることができますが、配列は順序を維持するために存在します。誰かがグローバル文字またはスペースを使用してファイル名を作成したset -f場合。IFS=$'\n'

もちろん、スクリプトを少し単純化し、番号付きの一時ファイルを作成することもできます。

答え2

:n移動したい:pコマンドを実行する以外に他の方法がない場合は、出力をファイルに出力してから次のようにしますless

svndiff () 
{
    d=$(mktemp -d /tmp/svndiffsXXXXX)
    for a in $(svn status | \grep ^M | sed 's/M       //');
    do
        svn diff "$a" > $(mktemp $d/diffXXXXX) 2>&1;
    done
    less "$d"/diff*
    rm -fr "$d"
}

(必要な方はお知らせいただければ番号を適用させていただきます。)

それ以外の場合は、すべてのコマンドを実行するシェルを呼び出し、接続された出力をless

答え3

GNU Parallelを使用すると、同様のことができます。

files=$(svn status | \grep ^M | sed 's/M       //' |
  parallel --files svn diff {})
less $files
rm $files

関連情報