web-dev-qa-db-ja.com

複数のコマンドをlessにパイプする

どのようにできるのか

{$several_commands} | less

lessをいくつかのファイルと見なし、:nおよび:pを使用してナビゲーションを有効にします。

それはより明確な説明ではないかもしれないので、例を考えてみましょう。現在機能を持っています

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

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

7
Tsathoggua

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

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'誰かがグロブ文字または空白を含むファイル名を作成した場合。

もちろん、スクリプトを少し簡略化して、代わりに番号付き一時ファイルを作成することもできます。

5
ilkkachu

: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にパイプします。

5
Ned64

GNU Parallelを使用すると、次のようなことができます:

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