考虑以下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
在别名中添加一个附加值)。