将当前目录保存为bash历史记录

时间:2009-06-03 15:01:18

标签: bash

我想保存发布每个命令的当前目录以及历史记录中的命令。为了不搞乱,我考虑在行尾添加当前目录作为注释。一个例子可能会有所帮助:

$ cd /usr/local/wherever
$ grep timmy accounts.txt

我想将bash保存为:

grep timmy accounts.txt # /usr/local/wherever

这个想法是这样我可以立即看到我发出命令的位置。

9 个答案:

答案 0 :(得分:47)

单线版

这是一个单行版本。这是原作。我还发布了一个short function version和一个long function version,其中包含一些附加功能。我喜欢这些函数版本,因为它们不会破坏你环境中的其他变量,并且它们比单行程更易读。这篇文章提供了一些关于它们如何工作的信息,这些信息在其他文章中可能不会重复。

将以下内容添加到~/.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"'

这使得历史记录条目看起来像:

rm subdir/file ### /some/dir

我使用###作为注释分隔符,将其与用户可能键入的注释区分开来,并在删除旧路径注释时减少冲突的可能性,否则如果在空白命令行上按Enter键则会累积。不幸的是,副作用是像echo " ### "这样的命令被破坏了,尽管这应该是相当罕见的。

有些人会发现我重复使用相同的变量名称是令人不愉快的。通常我不会,但在这里我试图尽量减少足迹。无论如何,它很容易改变。

它盲目地假设您没有使用HISTTIMEFORMAT或以其他方式修改历史记录。将date命令添加到注释中代替HISTTIMEFORMAT功能会很容易。但是,如果由于某种原因需要使用它,它仍然可以在子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命令也会看到它。

另一个是,除了注释副本之外,带有嵌入换行符的命令会在历史记录中留下未注释的副本。

可能还有其他问题出现。如果您发现任何问题,请告诉我。

如何运作

每次发出PROMPT_COMMAND主要提示时,Bash都会执行PS1变量中包含的命令。这个小脚本利用它来获取历史记录中的最后一个命令,为其添加注释并将其保存回来。

这里与评论分开:

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

答案 1 :(得分:17)

hcmnt - 长函数版

这是一个函数形式的长版本。这是一个怪物,但它增加了一些有用的功能。我还发布了一个单行(原始)和一个较短的功能。我喜欢这些函数版本,因为它们不会破坏你环境中的其他变量 它们比单线程更易读。阅读下面函数中单行和通信的条目,以获取有关其工作原理和一些限制的其他信息。我已将每个版本发布在自己的答案中,以使事情更有条理。

要使用此功能,请将其保存在名为hcmnt的文件中/usr/local/bin(如果需要,可以chmod +x),然后在{{1}像这样:

~/.bashrc

请勿编辑设置了source /usr/local/bin/hcmnt export hcmntextra='date "+%Y%m%d %R"' export PROMPT_COMMAND='hcmnt' PROMPT_COMMAND的函数文件。保持原样,使它们保持默认状态。如上所示,将它们包含在hcmntextra中,然后在其中进行修改以设置.bashrc的选项或更改或取消设置hcmnt。与短函数不同,使用此函数时,您必须同时使用hcmntextra变量集使用hcmntextra选项才能使该功能正常工作。

您可以在函数的注释中添加几个已记录的选项(带有几个示例)。一个值得注意的功能是将带有附加注释的历史记录条目记录到文件中,并保持实际历史记录不变。只是为了使用这个功能 像这样添加-e 文件名选项:

-l

您可以使用任意选项组合,但export PROMPT_COMMAND="hcmnt -l ~/histlog" -n是互斥的。

-t

更新2009-06-19 :添加了对日志记录(ip和tty)有用的选项,重复输入问题的解决方法,删除了无关的空分配

答案 2 :(得分:13)

您可以安装Advanced Shell History,这是一个将bashzsh历史记录写入sqlite数据库的开源工具。这会记录当前工作目录,命令退出代码,命令开始和停止时间,会话开始和停止时间,tty等。

如果要查询历史数据库,可以编写自己的SQL查询,保存它们并在捆绑的ash_query工具中使它们可用。有一些有用的预打包查询,但由于我非常了解SQL,我通常只需要在需要查找内容时以交互方式打开数据库并进行查询。

我发现一个非常有用的查询是查看当前工作目录的历史记录。它帮助我记住我在做某事时离开的地方。

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

使用当前工作目录(及其下面的任何内容)使用相同的历史记录:

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 - 我是该项目的作者和维护者。

答案 3 :(得分:6)

hcmnts - 短函数版

这是一个函数形式的简短版本。我还发布了一个单行(原始)和一个更长的功能,增加了几个功能。我喜欢这些函数版本,因为它们不会破坏你环境中的其他变量,并且它们比单行程更易读。阅读单行的条目,了解有关其工作原理和一些限制的其他信息。我已将每个版本发布在自己的答案中,以使事情更有条理。

要使用此功能,请将其保存在名为hcmnts的文件中/usr/local/bin(如果需要,可以chmod +x),然后在{{1}像这样:

~/.bashrc

如果您不想要日期和时间(或者您可以更改其格式或使用除source /usr/local/bin/hcmnts 之外的其他命令),请注释掉设置hcmntextra的行。

这就是它的全部内容。

date

答案 4 :(得分:2)

对于那些在zsh中想要这个的人,我会modified Jeet Sukumaran的实现和percol允许交互式关键字搜索和提取它所执行的命令或路径。它&#39 ; s还可以过滤掉重复的命令并隐藏字段(日期,命令,路径)

答案 5 :(得分:1)

Gentleman这样做效果更好..我唯一想不通的是如何让脚本在登录时不记录到syslog并记录历史记录中的最后一个命令。但到目前为止,它就像一个魅力。

#!/bin/bash

trackerbash() {
    # adds comments to bash history entries

    # by Dennis Williamson
    # http://stackoverflow.com/questions/945288/saving-current-directory-to-bash-history
    # (thanks to Lajos Nagy for the idea)

    #Supper Enhanced by QXT


    # INSTALLATION: source this file in your .bashrc

    export HISTTIMEFORMAT=
#    export HISTTIMEFORMAT='%F   %T    '

    local hcmnt
    local cwd
    local extra
    local thistty
    local whoiam
    local sudouser
    local shelldate
    local TRACKIP
    local TRACKHOST


            thistty=`/usr/bin/tty|/bin/cut -f3-4 -d/`
            whoiam=`/usr/bin/whoami`
            sudouser=`last |grep $thistty |head -1 | awk '{ print $1 }' |cut -c 1-10`
            hcmnt=$(history 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"
            history -w 

}
export PROMPT_COMMAND='trackerbash'

答案 6 :(得分:1)

完全公开:我是FOSS工具的作者
shournal - A (file-) journal for your shell
使用 bash集成,命令的工作目录也存储在shournal的sqlite数据库中,并且可以通过

检索
shournal --query -cmdcwd "$PWD"

查询子工作目录可以使用

shournal --query -cmdcwd -like "$PWD/%"

答案 7 :(得分:0)

这是我使用的单行内容。坚持这里是因为它非常简单,而且我对每个会话的历史没有任何问题,我只是希望拥有工作目录的历史记录。

如果您的用户界面太多,也会出现上面的单行内容。

export PROMPT_COMMAND='if [ "$(id -u)" -ne 0 ]; then echo "$(date "+%Y-%m-%d.%H:%M:%S") $(pwd) $(history 1)" >> ~/.bash.log; fi'

由于我的家庭目的通常是一个交叉安装的gluster thingy,这有一个副作用,是我所做过的一切历史。 (可选)将$(hostname)添加到上面的echo命令中......具体取决于您的工作环境。

即使有100k条目,grep也足够好了。不需要sqlite登录吧。只是不要在命令行输入密码,你就是好的。无论如何,密码都是90年代的技术!

此外,搜索我倾向于这样做:

function hh() {
    grep "$1" ~/.bash.log
}

答案 8 :(得分:0)

您可以考虑一个独立的项目(由我编写),该项目支持保存每个命令的路径:https://github.com/chrissound/MoscoviumOrange

您可以在其中向Bash添加钩子,以使用以下命令保存每个条目:

$(jq -n --arg command "$1" --arg path "$PWD" '{"command":$command, "path":$path}' | "$(echo 'readlink -f $(which nc)' | nix run nixpkgs.netcat)" -N -U ~/.config/moscoviumOrange/monitor.soc &)