将多个命令通过管道传输到 less

Tsa*_*gua 7 less bash pipe

我能怎么做

{$several_commands} | less
Run Code Online (Sandbox Code Playgroud)

并将less其视为多个文件,并使用:n和启用导航:p

这可能不是更清楚的解释,所以让我们考虑一个例子。我目前有一个功能

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

目的显然是查看less我所有修改过的文件的不同之处。但是使用这种语法,我必须使用 keyQ来关闭一个“文件”并打开下一个。我希望能够使用less命令:n(下一个文件)和:p(上一个文件)在文件之间导航。我怎样才能做到这一点 ?

Ned*_*d64 5

如果您想移动: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"
}
Run Code Online (Sandbox Code Playgroud)

(如果您需要它们,请告诉我,我们可以申请编号。)

否则,您可以调用一个 shell 执行您的所有命令,然后将连接的输出通过管道传输到less.


ilk*_*chu 5

您可以使用流程替换:

less -f <(svn diff this) <(svn diff that)
Run Code Online (Sandbox Code Playgroud)

但这很难在循环中使用。可能最好只使用临时文件:

#!/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"
Run Code Online (Sandbox Code Playgroud)

以上尝试使文件名在临时文件的名称中可见,并对斜杠和前导点进行了一些清理。(如果你得到类似的路径./foo/bar。我不记得如何svn输出文件名,但无论如何......)

该数组用于保持顺序,尽管正如@Kusalananda 所说"$dir"/*,如果顺序无关紧要,我们可以改为这样做。set -fIFS=$'\n'万一有人有水珠字符或空格创建文件名。

当然,我们可以稍微简化脚本并创建编号的临时文件。