保存当前目录为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命令添加到评论中以替代HISTTIMEFORMATfunction将很容易。 但是,如果由于某种原因需要使用它,它仍会在子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_COMMANDvariables中的命令。 这个小脚本利用它来获取历史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_COMMANDhcmntextra设置的函数文件。 保持原样,保持默认。 如上所示将它们包含在.bashrc中,并在那里编辑它们以设置hcmnt选项或更改或取消设置hcmntextra 。 与short函数不同的是,在这个函数中,您必须同时设置hcmntextravariables, 使用-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 ,这是一个开源工具,可以将bashzsh历史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


             thistt​​y =`/ usr / bin / tty | / bin / cut -f3-4 -d /`
             whoiam =`的/ usr /斌/ whoami`
             sudouser =`last | grep $ thistt​​y | 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 $ thistt​​y | head -1 |  awk'{print $ 3}'`


             logger -p local1.notice -t bashtracker -i  - “$ sudouser $ {USER}:$ thistt​​y:$ 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 }