通过管道将多个命令传递给 less

通过管道将多个命令传递给 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我修改的所有文件的差异。但使用这种语法,我必须使用 keyQ关闭一个“文件”并打开下一个“文件”。我希望能够使用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"
}

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

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

答案3

使用 GNU Parallel 你可以做类似的事情:

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

相关内容