保存当前目录为bash历史
我想保存每个命令在历史命令旁边的当前目录。 为了不把事情搞砸,我想在行尾添加当前目录作为注释。 一个例子可能有助于:
$ cd /usr/local/wherever $ grep timmy accounts.txt
我想bash保存最后的命令为:
grep timmy accounts.txt # /usr/local/wherever
这个想法是,我可以立即看到我发布命令的地方。
单线版本
这是一个单线版本。 这是原来的。 我还发布了一个简短的function版本和一个长function版本,并增加了几个function。 我喜欢函数版本,因为它们不会在你的环境中打破其他variables,并且比单行代码更可读。 这篇文章有一些关于它们如何工作的信息,其他信息可能不会被复制。
将以下内容添加到~/.bashrc
文件中:
export PROMPT_COMMAND='hpwd=$(history 1); hpwd="${hpwd# *[0-9]* }"; if [[ ${hpwd%% *} == "cd" ]]; then cwd=$OLDPWD; else cwd=$PWD; fi; hpwd="${hpwd% ### *} ### $cwd"; history -s "$hpwd"'
这使得历史logging看起来像:
rm subdir/file ### /some/dir
我使用###
作为注释分隔符来将其与用户可能键入的注释区分开来,并在删除旧path注释时减less冲突的机会,否则,如果在空白命令行上按下Enter键,注释将会累积。 不幸的是,副作用是像echo " ### "
这样的命令被破坏,尽pipe这应该是相当罕见的。
有些人会发现,我重复使用相同的variables名称是不愉快的事实。 通常我不会,但在这里我正在尽量减less足迹。 无论如何都很容易改变。
它一味地认为你没有使用HISTTIMEFORMAT
或以其他方式修改历史logging。 将date
命令添加到评论中以替代HISTTIMEFORMAT
function将很容易。 但是,如果由于某种原因需要使用它,它仍会在子shell中工作,因为它会自动取消设置:
$ htf="%Y-%m-%d %R " # save it for re-use $ (HISTTIMEFORMAT=$htf; history 20)|grep 11:25
有几个非常小的问题。 一个是,如果你使用这样的history
命令,例如:
$ history 3 echo "hello world" ### /home/dennis ls -l /tmp/file ### /home/dennis history 3
结果将不会显示history
命令本身的评论,即使您按下向上箭头或发出其他history
命令时也会看到它。
另一个是embedded换行符的命令除了注释的副本之外还在历史中留下未注释的副本。
可能还有其他问题出现。 让我知道,如果你find任何。
怎么运行的
每次发出PS1
主提示时,Bash都会执行包含在PROMPT_COMMAND
variables中的命令。 这个小脚本利用它来获取历史logging中的最后一个命令,添加一个注释并保存。
在这里它分裂与评论:
hpwd=$(history 1) # grab the most recent command hpwd="${hpwd# *[0-9]* }" # strip off the history line number if [[ ${hpwd%% *} == "cd" ]] # if it's a cd command, we want the old directory then # so the comment matches other commands "where *were* you when this was done?" cwd=$OLDPWD else cwd=$PWD fi hpwd="${hpwd% ### *} ### $cwd" # strip off the old ### comment if there was one so they # don't accumulate, then build the comment history -s "$hpwd" # replace the most recent command with itself plus the comment
hcmnt – 长function版本
这是一个函数forms的长版本。 这是一个怪物 ,但它增加了一些有用的function。 我还发布了一行(原文)和一个较短的函数。 我喜欢函数版本,因为它们不会在你的环境中打破其他variables,并且比单行代码更可读。 请阅读下面的函数和单行的条目,了解它是如何工作的,以及一些限制的更多信息。 我已经发布每个版本在自己的答案,以保持更有条理的事情。
要使用这个文件,把它保存在一个名为hcmnt
的文件中,如/usr/local/bin
(如果你愿意的话,可以用chmod +x
),然后在你的~/.bashrc
:
source /usr/local/bin/hcmnt export hcmntextra='date "+%Y%m%d %R"' export PROMPT_COMMAND='hcmnt'
不要编辑PROMPT_COMMAND
或hcmntextra
设置的函数文件。 保持原样,保持默认。 如上所示将它们包含在.bashrc
中,并在那里编辑它们以设置hcmnt
选项或更改或取消设置hcmntextra
。 与short函数不同的是,在这个函数中,您必须同时设置hcmntextra
variables, 并使用-e
选项来使该function正常工作。
你可以在函数的注释中添加几个已经logging的选项(有几个例子)。 一个值得注意的function是将历史logging与附加注释logging到一个文件中,并保持实际的历史logging不变。 为了使用这个函数,只需要添加-l
filename选项就可以了:
export PROMPT_COMMAND="hcmnt -l ~/histlog"
除了-n
和-t
是互斥的,你可以使用任意选项的组合。
#!/bin/bash hcmnt() { # adds comments to bash history entries (or logs them) # by Dennis Williamson - 2009-06-05 - updated 2009-06-19 # http://stackoverflow.com/questions/945288/saving-current-directory-to-bash-history # (thanks to Lajos Nagy for the idea) # the comments can include the directory # that was current when the command was issued # plus optionally, the date or other information # set the bash variable PROMPT_COMMAND to the name # of this function and include these options: # -e - add the output of an extra command contained in the hcmntextra variable # -i - add ip address of terminal that you are logged in *from* # if you're using screen, the screen number is shown # if you're directly logged in, the tty number or X display number is shown # -l - log the entry rather than replacing it in the history # -n - don't add the directory # -t - add the from and to directories for cd commands # -y - add the terminal device (tty) # text or a variable # Example result for PROMPT_COMMAND='hcmnt -et $LOGNAME' # when hcmntextra='date "+%Y%m%d %R"' # cd /usr/bin ### mike 20090605 14:34 /home/mike -> /usr/bin # Example for PROMPT_COMMAND='hcmnt' # cd /usr/bin ### /home/mike # Example for detailed logging: # when hcmntextra='date "+%Y%m%d %R"' # and PROMPT_COMMAND='hcmnt -eityl ~/.hcmnt.log $LOGNAME@$HOSTNAME' # $ tail -1 ~/.hcmnt.log # cd /var/log ### dave@hammerhead /dev/pts/3 192.168.1.1 20090617 16:12 /etc -> /var/log # INSTALLATION: source this file in your .bashrc # will not work if HISTTIMEFORMAT is used - use hcmntextra instead export HISTTIMEFORMAT= # HISTTIMEFORMAT still works in a subshell, however, since it gets unset automatically: # $ htf="%Y-%m-%d %R " # save it for re-use # $ (HISTTIMEFORMAT=$htf; history 20)|grep 11:25 local script=$FUNCNAME local hcmnt= local cwd= local extra= local text= local logfile= local options=":eil:nty" local option= OPTIND=1 local usage="Usage: $script [-e] [-i] [-l logfile] [-n|-t] [-y] [text]" local newline=$'\n' # used in workaround for bash history newline bug local histline= # used in workaround for bash history newline bug local ExtraOpt= local LogOpt= local NoneOpt= local ToOpt= local tty= local ip= # *** process options to set flags *** while getopts $options option do case $option in e ) ExtraOpt=1;; # include hcmntextra i ) ip="$(who --ips -m)" # include the terminal's ip address ip=($ip) ip="${ip[4]}" if [[ -z $ip ]] then ip=$(tty) fi;; l ) LogOpt=1 # log the entry logfile=$OPTARG;; n ) if [[ $ToOpt ]] then echo "$script: can't include both -n and -t." echo $usage return 1 else NoneOpt=1 # don't include path fi;; t ) if [[ $NoneOpt ]] then echo "$script: can't include both -n and -t." echo $usage return 1 else ToOpt=1 # cd shows "from -> to" fi;; y ) tty=$(tty);; : ) echo "$script: missing filename: -$OPTARG." echo $usage return 1;; * ) echo "$script: invalid option: -$OPTARG." echo $usage return 1;; esac done text=($@) # arguments after the options are saved to add to the comment text="${text[*]:$OPTIND - 1:${#text[*]}}" # *** process the history entry *** hcmnt=$(history 1) # grab the most recent command # save history line number for workaround for bash history newline bug histline="${hcmnt% *}" hcmnt="${hcmnt# *[0-9]* }" # strip off the history line number if [[ -z $NoneOpt ]] # are we adding the directory? then if [[ ${hcmnt%% *} == "cd" ]] # if it's a cd command, we want the old directory then # so the comment matches other commands "where *were* you when this was done?" if [[ $ToOpt ]] then cwd="$OLDPWD -> $PWD" # show "from -> to" for cd else cwd=$OLDPWD # just show "from" fi else cwd=$PWD # it's not a cd, so just show where we are fi fi if [[ $ExtraOpt && $hcmntextra ]] # do we want a little something extra? then extra=$(eval "$hcmntextra") fi # strip off the old ### comment if there was one so they don't accumulate # then build the string (if text or extra aren't empty, add them plus a space) hcmnt="${hcmnt% ### *} ### ${text:+$text }${tty:+$tty }${ip:+$ip }${extra:+$extra }$cwd" if [[ $LogOpt ]] then # save the entry in a logfile echo "$hcmnt" >> $logfile || echo "$script: file error." ; return 1 else # workaround for bash history newline bug if [[ $hcmnt != ${hcmnt/$newline/} ]] # if there a newline in the command then history -d $histline # then delete the current command so it's not duplicated fi # replace the history entry history -s "$hcmnt" fi } # END FUNCTION hcmnt # set a default (must use -e option to include it) export hcmntextra='date "+%Y%m%d %R"' # you must be really careful to get the quoting right # start using it export PROMPT_COMMAND='hcmnt'
更新2009年6月19日 :添加选项有用的日志logging(ip和tty),重复条目问题的解决方法,删除多余的空分配
您可以安装高级shell历史logging ,这是一个开源工具,可以将bash
或zsh
历史logging写入sqlite数据库。 它logging了当前的工作目录,命令退出代码,命令启动和停止时间,会话开始和停止时间,tty等等。
如果要查询历史数据库,可以编写自己的SQL查询,将其保存并在捆绑的ash_query
工具中使用。 有一些有用的预打包查询,但由于我知道SQL很好,所以我通常只需要打开数据库并在需要查找时交互式查询。
但是,我发现一个查询非常有用的查询是查看当前工作目录的历史logging。 这有助于我记得当我正在做什么的时候,我从哪里离开了。
vagrant@precise32:~$ ash_query -q CWD session when what 1 2014-08-27 17:13:07 ls -la 2014-08-27 17:13:09 cd .ash 2014-08-27 17:16:27 ls 2014-08-27 17:16:33 rm -rf advanced-shell-history/ 2014-08-27 17:16:35 ls 2014-08-27 17:16:37 less postinstall.sh 2014-08-27 17:16:57 sudo reboot -n
和使用当前工作目录(以及其下的任何内容)相同的历史logging:
vagrant@precise32:~$ ash_query -q RCWD session where when what 1 /home/vagrant/advanced-shell-history 2014-08-27 17:11:34 nano ~/.bashrc 2014-08-27 17:12:54 source /usr/lib/advanced_shell_history/bash 2014-08-27 17:12:57 source /usr/lib/advanced_shell_history/bash 2014-08-27 17:13:05 cd /home/vagrant 2014-08-27 17:13:07 ls -la 2014-08-27 17:13:09 cd .ash /home/vagrant/.ash 2014-08-27 17:13:10 ls 2014-08-27 17:13:11 ls -l 2014-08-27 17:13:16 sqlite3 history.db 2014-08-27 17:13:43 ash_query 2014-08-27 17:13:50 ash_query -Q 2014-08-27 17:13:56 ash_query -q DEMO 2014-08-27 17:14:39 ash_query -q ME 2014-08-27 17:16:26 cd /home/vagrant 2014-08-27 17:16:27 ls 2014-08-27 17:16:33 rm -rf advanced-shell-history/ 2014-08-27 17:16:35 ls 2014-08-27 17:16:37 less postinstall.sh 2014-08-27 17:16:57 sudo reboot -n
FWIW – 我是该项目的作者和维护者。
hcmnts – 短function版本
这是一个函数forms的简短版本。 我还发布了一个单行(原文)和一个更长的function,几个附加function。 我喜欢函数版本,因为它们不会在你的环境中打破其他variables,并且比单行代码更可读。 阅读单行的条目,了解有关如何工作和一些限制的更多信息。 我已经发布每个版本在自己的答案,以保持更有条理的事情。
要使用这个文件,把它保存在一个名为hcmnts
的文件中,如/usr/local/bin
(如果你愿意的话,可以用chmod +x
),然后像这样在~/.bashrc
它:
source /usr/local/bin/hcmnts
注释掉设置hcmntextra
的行,如果你不想要date和时间(或者你可以改变它的格式或者使用除了date
以外的其他命令)。
这里的所有都是它的。
#!/bin/bash hcmnts() { # adds comments to bash history entries # the *S*hort version of hcmnt (which has many more features) # by Dennis Williamson # http://stackoverflow.com/questions/945288/saving-current-directory-to-bash-history # (thanks to Lajos Nagy for the idea) # INSTALLATION: source this file in your .bashrc # will not work if HISTTIMEFORMAT is used - use hcmntextra instead export HISTTIMEFORMAT= # HISTTIMEFORMAT still works in a subshell, however, since it gets unset automatically: # $ htf="%Y-%m-%d %R " # save it for re-use # $ (HISTTIMEFORMAT=$htf; history 20)|grep 11:25 local hcmnt local cwd local extra hcmnt=$(history 1) hcmnt="${hcmnt# *[0-9]* }" if [[ ${hcmnt%% *} == "cd" ]] then cwd=$OLDPWD else cwd=$PWD fi extra=$(eval "$hcmntextra") hcmnt="${hcmnt% ### *}" hcmnt="$hcmnt ### ${extra:+$extra }$cwd" history -s "$hcmnt" } export hcmntextra='date +"%Y%m%d %R"' export PROMPT_COMMAND='hcmnts'
绅士这工作更好..唯一我无法弄清楚是如何使脚本不login到系统日志login和logging历史上的最后一个命令。 但到目前为止,它就像一个魅力。
#!/斌/庆典 trackerbash(){ #为bash历史logging添加注释 #丹尼斯威廉姆森 #http://stackoverflow.com/questions/945288/saving-current-directory-to-bash-history #(感谢Lajos Nagy的想法) QXT增强的#Supper #安装:将源文件放在你的.bashrc文件中 导出HISTTIMEFORMAT = #export HISTTIMEFORMAT ='%F%T' 当地hcmnt 本地cwd 当地的额外 当地的诡计 本地whoiam 当地sudouser 本地shelldate 本地TRACKIP 本地TRACKHOST thistty =`/ usr / bin / tty | / bin / cut -f3-4 -d /` whoiam =`的/ usr /斌/ whoami` sudouser =`last | grep $ thistty | head -1 | awk'{print $ 1}'| cut -c 1-10` hcmnt = $(历史1) hcmnt =“$ {hcmnt#* [0-9] *}” CWD =`pwd` hcmnt =“$ {hcmnt%### *}” hcmnt =“$ hcmnt $ {extra:+ $ extra}” shelldate =`date +“%Y%b%d%R:%S”` TRACKHOST =`whoami | sed -r“s /.* \((。*)\)。* / \\ 1 /”` TRACKIP =`last | grep $ thistty | head -1 | awk'{print $ 3}'` logger -p local1.notice -t bashtracker -i - “$ sudouser $ {USER}:$ thistty:$ TRACKIP:$ shelldate:$ cwd:$ hcmnt” 历史-w } export PROMPT_COMMAND ='trackerbash'
对于那些在zsh中需要这个的人来说,我修改了 Jeet Sukumaran的实现和percol,允许交互式关键字search和提取命令或执行的path。还可以过滤掉重复的命令并隐藏字段(date,命令,path)
这是我使用的一个class轮。 在这里坚持下去是因为它非常简单,而且我对每个会话历史都没有问题,所以我也想要在工作目录中有一个历史logging。
export PROMPT_COMMAND='if [ "$(id -u)" -ne 0 ]; then echo "$(date "+%Y-%m-%d.%H:%M:%S") $(pwd) $(history 1)" >> ~/.bash.log; fi'
由于我的家庭目录通常是一个十字架装腔作势的事情,这有一个副作用,是我所做的一切的历史。 根据您的工作环境,可以select将$(hostname)
添加到上面的echo命令中。
即使有10万个条目,grep也不够好。 不需要sqlitelogging它。 只要不要在命令行中input密码,你就很好。 无论如何,密码是90年代的技术!
另外,为了search,我倾向于这样做:
function hh() { grep "$1" ~/.bash.log }