Insertar el texto de la línea de comando antes de la salida en stdout (para canalización/redirección)

Insertar el texto de la línea de comando antes de la salida en stdout (para canalización/redirección)

Considere las siguientes bashconstrucciones:

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

En este caso, list-redir.txty list-tee.txtserá idéntico y contendrá la lista de archivos como se esperaba; p.ej

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

Mi pregunta es: ¿cómo podría escribir un comando de este tipo e insertar el texto de la línea de comando como lo primero en la salida estándar, de modo que el archivo finalmente comience con la línea de comando como primero? Como ejemplo, el archivo list-redir.txten ese caso se vería así:

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

... lo que también implica que el carácter # se puede anteponer a la línea de comando insertada.

¿Hay algo que pueda usar para esto, pero con el mínimo de cambios al escribir con respecto a las líneas de comando originales ( ls /usr/include/asm > list-redir.txt...)?

Respuesta1

Un truco simple (y feo) sería agregar esto a tu ~/.bashrc:

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

Luego ejecutarías tu comando como

echorun ls /usr > list-redir.txt

Eso no le permitirá diferenciar entre ls /usr >fooy ls /usr | tee foopero se agregará # ls /usral comienzo de foo.

Respuesta2

Podrías hacer esto:

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

Al menos creo que esto es lo que quieres que se haga. Esto produciría resultados como:

 $ cat <./list-redir.txt

 ###OUTPUT###

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

Respuesta3

También puede consultar el scriptcomando que registrará su sesión de terminal, incluido lo que escribe y todos los resultados. Sin embargo, a veces puede resultar un poco complicado, ya que registrará todo lo que escriba, incluidos los retrocesos, 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

Respuesta4

En realidad, me acabo de dar cuenta de que es posible que la respuesta de @terdon no funcione con una canalización de comandos más complicada; así que se me ocurrió el siguiente alias (llamado erabreviatura de @tendon echorun):

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

La idea es, básicamente, que |erse inserte antes de la última tubería o se redirija en una línea de comando; entonces, es una coincidencia afortunada que en ese punto, ¡ history 1se refiera exactamente a la línea de comando actual! Por lo tanto, se puede repetir primero, antes que el resto de la entrada estándar (lo que hay en ese punto), mediante cat. Y así, ahora podemos hacer cosas 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

Por lo tanto, tenemos una línea de comando completa de múltiples canalizaciones, y no tenemos que preocuparnos por escapar de nada; básicamente, simplemente agregamos era la última canalización. La única pequeña molestia es el número del historial (no me molesta mucho, de lo contrario agregaría uno adicional awken el alias).

información relacionada