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 /usrfoo

答え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

er実は、@terdon からの回答は、より複雑なコマンド パイプラインでは機能しない可能性があることに気付きました。そこで、次のエイリアス ( @tendon の短縮名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

関連情報