canaliza vários comandos para menos

6

Como posso fazer

{$several_commands} | less

e tenha less como arquivos e ative a navegação usando :n e :p .

Essa pode não ser a explicação mais clara, portanto, vamos considerar um exemplo. Atualmente tenho uma função

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

O objetivo, obviamente, é ver com less a diferença de todos os meus arquivos modificados. Mas com esta sintaxe, eu tenho que usar a chave Q para fechar um "arquivo" e abrir o próximo. Eu gostaria de poder navegar entre arquivos com os less comandos :n (próximo arquivo) e :p (arquivo anterior). Como posso fazer isso?

    
por Tsathoggua 13.02.2018 / 17:27

3 respostas

5

Você pode usar a substituição de processos:

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

Mas isso é difícil de usar em um loop. Provavelmente, é melhor usar apenas arquivos temporários:

#!/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"

O acima tenta manter os nomes de arquivos visíveis nos nomes dos arquivos temporários, com alguma limpeza para barras e pontos principais. (No caso de você obter caminhos como ./foo/bar . Não consigo me lembrar de como svn exibe os nomes dos arquivos, mas de qualquer forma ...)

A matriz está lá para manter o pedido, embora, como disse @Kusalananda, pudéssemos fazer apenas "$dir"/* , se a ordem não importasse. set -f e IFS=$'\n' no caso de alguém criar nomes de arquivo com caracteres glob ou espaço em branco.

É claro que podemos simplificar o script e criar, digamos, arquivos temporários numerados.

    
por 13.02.2018 / 17:42
5

Se você quiser mover com :n e :p , não há outra maneira senão executar os comandos, enviar as saídas para os arquivos e, em seguida, less deles:

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"
}

(Se você precisar deles, me avise e podemos aplicar a numeração.)

Caso contrário, você poderia chamar um shell executando todos os seus comandos e, em seguida, enviar a saída concatenada para less .

    
por 13.02.2018 / 17:40
2

Usando o GNU Parallel, você pode fazer algo como:

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

Tags