Вставка текста командной строки перед выводом в stdout (для конвейера/перенаправления)

Вставка текста командной строки перед выводом в stdout (для конвейера/перенаправления)

Рассмотрим следующие bashконструкции:

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

В этом случае list-redir.txtи list-tee.txtбудут идентичны и будут содержать список файлов, как и ожидалось; например

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

Мой вопрос - как я могу написать такую ​​команду и сделать так, чтобы текст командной строки был вставлен первым в стандартный вывод - так, чтобы файл в конечном итоге начинался с командной строки в качестве первого? Например, файл list-redir.txtв этом случае будет выглядеть так:

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

... что также подразумевает, что символ # может быть добавлен к вставленной командной строке.

Есть ли что-нибудь, что я мог бы использовать для этого, но с минимальными изменениями в наборе по сравнению с исходными командными строками ( ls /usr/include/asm > list-redir.txt...)?

решение1

Простым (и некрасивым) приемом было бы добавить это в ваш ~/.bashrc:

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

Затем вы запускаете команду как

echorun ls /usr > list-redir.txt

Это не позволит вам различать ls /usr >fooи , ls /usr | tee fooно добавит # ls /usrв начало foo.

решение2

Вы можете просто сделать это:

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

По крайней мере, я думаю, что это то, что вы хотите сделать. Это даст такие результаты:

 $ cat <./list-redir.txt

 ###OUTPUT###

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

решение3

Вы также можете взглянуть на scriptкоманду, которая будет записывать ваш сеанс терминала, включая то, что вы печатаете, и весь вывод. Иногда это может быть немного запутанным, так как она будет записывать все, что вы печатаете, включая любые возвраты и т. д.

$ 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

решение4

На самом деле, только что понял, что ответ от @terdon может не сработать с более сложным конвейером команд; поэтому я придумал следующий псевдоним (названный erкак сокращение от @tendon's echorun):

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

Идея в том, что, по сути, это |erдолжно быть вставлено перед последним конвейером или перенаправлением в командной строке; тогда, это действительно удачное совпадение, что в этой точке, history 1точно относится к текущей командной строке! Таким образом, это может быть отображено первым, перед остальной частью (то, что находится в этой точке) стандартного ввода, с помощью cat. И поэтому теперь мы можем делать такие вещи, как:

$ 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

Таким образом, у нас есть полная командная строка из нескольких каналов - и нам не нужно беспокоиться об экранировании чего-либо - в основном, просто добавьте erк последнему каналу. Единственное небольшое замечание - это номер истории (он меня не так уж и беспокоит, иначе я бы добавил дополнительный awkв псевдоним).

Связанный контент