Inserindo o texto da linha de comando antes da saída em stdout (para pipe/redirecionamento)

Inserindo o texto da linha de comando antes da saída em stdout (para pipe/redirecionamento)

Considere as seguintes bashconstruções:

ls /usr/include/asm > list-redir.txt
ls /usr/include/asm | tee list-tee.txt

Neste caso, list-redir.txte list-tee.txtserá idêntico e conterá a listagem dos arquivos conforme o esperado; por exemplo

$ head -5 list-redir.txt
a.out.h
auxvec.h
bitsperlong.h
boot.h
bootparam.h [...]

Minha pergunta é: como eu poderia escrever tal comando e ter o texto da linha de comando inserido como a primeira coisa na saída padrão - de modo que o arquivo eventualmente comece com a linha de comando primeiro? Por exemplo, o arquivo list-redir.txtnesse caso ficaria assim:

$ head -5 list-redir.txt
# ls /usr/include/asm
a.out.h
auxvec.h
bitsperlong.h
boot.h [...]

... o que também implica que o caractere # pode ser anexado à linha de comando inserida.

Existe algo que eu possa usar para isso - mas com o mínimo de alteração na digitação em relação às linhas de comando originais ( ls /usr/include/asm > list-redir.txt...)?

Responder1

Um truque simples (e feio) seria adicionar isto ao seu ~/.bashrc:

echorun(){
    echo "# $@";
    "$@"
}

Você então executaria seu comando como

echorun ls /usr > list-redir.txt

Isso não permitirá que você diferencie entre ls /usr >fooe ls /usr | tee foo, mas será anexado # ls /usrao início de foo.

Responder2

Você poderia simplesmente fazer isso:

{   cmd="ls /usr/include/asm"
    echo "$cmd" ; $cmd
} >./list-redir.txt

Pelo menos acho que é isso que você quer que seja feito. Isso produziria resultados como:

 $ cat <./list-redir.txt

 ###OUTPUT###

   ls /usr/include/asm
 #output of above command#
   ...

Responder3

Você também pode consultar o scriptcomando que registrará sua sessão de terminal, incluindo o que você digita e toda a saída. Às vezes, pode ficar um pouco confuso, pois grava tudo o que você digita, incluindo retrocessos, etc.

$ script
Script started, file is typescript
$ ls /usr/include/asm
a.out.h          ioctl.h      mtrr.h             setup.h         termios.h
auxvec.h         ioctls.h     param.h            shmbuf.h        types.h
bitsperlong.h    ipcbuf.h     poll.h             sigcontext32.h  ucontext.h
boot.h           ist.h        posix_types_32.h   sigcontext.h    unistd_32.h
bootparam.h      kvm.h        posix_types_64.h   siginfo.h       unistd_64.h
byteorder.h      kvm_para.h   posix_types.h      signal.h        unistd.h
debugreg.h       ldt.h        prctl.h            socket.h        vm86.h
e820.h           mce.h        processor-flags.h  sockios.h       vsyscall.h
errno.h          mman.h       ptrace-abi.h       statfs.h
fcntl.h          msgbuf.h     ptrace.h           stat.h
hw_breakpoint.h  msr.h        resource.h         swab.h
hyperv.h         msr-index.h  sembuf.h           termbits.h
$ exit
exit
Script done, file is typescript
$ cat typescript
Script started on Sat 29 Aug 2015 10:32:52 AM EDT
$ ls /usr/include/asm
a.out.h          ioctl.h      mtrr.h             setup.h         termios.h
auxvec.h         ioctls.h     param.h            shmbuf.h        types.h
bitsperlong.h    ipcbuf.h     poll.h             sigcontext32.h  ucontext.h
boot.h           ist.h        posix_types_32.h   sigcontext.h    unistd_32.h
bootparam.h      kvm.h        posix_types_64.h   siginfo.h       unistd_64.h
byteorder.h      kvm_para.h   posix_types.h      signal.h        unistd.h
debugreg.h       ldt.h        prctl.h            socket.h        vm86.h
e820.h           mce.h        processor-flags.h  sockios.h       vsyscall.h
errno.h          mman.h       ptrace-abi.h       statfs.h
fcntl.h          msgbuf.h     ptrace.h           stat.h
hw_breakpoint.h  msr.h        resource.h         swab.h
hyperv.h         msr-index.h  sembuf.h           termbits.h
$ exit
exit

Script done on Sat 29 Aug 2015 10:33:00 AM EDT

Responder4

Na verdade, acabei de perceber que a resposta do @terdon pode não funcionar com um pipeline de comando mais complicado; então criei o seguinte alias (nomeado ercomo abreviação de @tendon's echorun):

#alias er=' cat <(echo "# cmd: $(history 1)") - | tee' # last tee is not needed, so:
alias er=' cat <(echo "# cmd: $(history 1)") -'

A ideia é, basicamente, que |erseja inserido antes do último pipe ou redirecionado em uma linha de comando; então, é realmente uma feliz coincidência que, nesse ponto, history 1se refira exatamente à linha de comando atual! Assim, ele pode ser ecoado primeiro, antes do restante (o que está nesse ponto) da entrada padrão, por cat. E então, agora podemos fazer coisas como:

$ ls /usr/include/asm | grep 'p*.h' | grep 'osix' |er | tee mylist.txt
# cmd:   125  ls /usr/include/asm | grep 'p*.h' | grep 'osix' |er | tee mylist.txt
posix_types_32.h
posix_types_64.h
posix_types.h
$ ls /usr/include/asm | grep 's*.h' | grep 'ig' |er >> mylist.txt
$ cat mylist.txt 
# cmd:   125  ls /usr/include/asm | grep 'p*.h' | grep 'osix' |er | tee mylist.txt
posix_types_32.h
posix_types_64.h
posix_types.h
# cmd:   126  ls /usr/include/asm | grep 's*.h' | grep 'ig' |er >> mylist.txt
sigcontext32.h
sigcontext.h
siginfo.h
signal.h

Assim temos linha de comando completa de múltiplos pipes - e não precisamos nos preocupar em escapar de nada - basicamente, basta adicionar erao último pipe. O único problema é o número do histórico (não me incomoda muito, caso contrário, eu adicionaria um adicional awkno alias).

informação relacionada