168

命令如下

  511  clear
  512  history
  513  history -d 505
  514  history
  515  history -d 507 510 513
  516  history
  517  history -d 509
  518  history
  519  history -d 511
  520  history

我可以删除单个history -d 511,但是如何在 shell 中使用单个命令删除最后 10 个命令和 10 个命令之间的历史记录?

我们可以编写一个 bash 脚本并执行以删除历史记录吗?

4

20 回答 20

122

您是否尝试过直接编辑历史文件:

~/.bash_history
于 2013-02-07T12:07:37.050 回答
102

我的答案基于以前的答案,但增加了颠倒顺序,以便从最近到最近删除历史项目。

获取您当前的历史记录(调整您想查看的行数):

history | tail -n 10

这给了我类似的东西

1003  25-04-2016 17:54:52 echo "Command 1"
1004  25-04-2016 17:54:54 echo "Command 2"
1005  25-04-2016 17:54:57 echo "Command 3"
1006  25-04-2016 17:54:59 echo "Command 4"
1007  25-04-2016 17:55:01 echo "Command 5"
1008  25-04-2016 17:55:03 echo "Command 6"
1009  25-04-2016 17:55:07 echo "Command 7"
1010  25-04-2016 17:55:09 echo "Command 8"
1011  25-04-2016 17:55:11 echo "Command 9"
1012  25-04-2016 17:55:14 echo "Command 10"

选择要删除的项目的开始和结束位置。我将删除条目 1006 到 1008。

for h in $(seq 1006 1008); do history -d 1006; done

这将为 1006 生成history -d命令,然后 1007 变为 1006 并删除 1006,然后 1008(变为 1007)现在是 1006 并被删除。

如果我还想删除历史记录删除命令,那么它会有点复杂,因为您需要知道当前最大历史记录条目。

你可以得到这个(可能有更好的方法):

history 1 | awk '{print $1}'

把它放在一起你可以用它来删除一个范围,也可以删除历史删除命令:

for h in $(seq 1006 1008); do history -d 1006; done; history -d $(history 1 | awk '{print $1}')

将这一切包装在一个函数中以添加到您的~/.bashrc

histdel(){
  for h in $(seq $1 $2); do
    history -d $1
  done
  history -d $(history 1 | awk '{print $1}')
  }

删除命令 4、5 和 6 (1049-1051) 并隐藏证据的示例:

[18:21:02 jonathag@gb-slo-svb-0221 ~]$ history 11
 1046  25-04-2016 18:20:47 echo "Command 1"
 1047  25-04-2016 18:20:48 echo "Command 2"
 1048  25-04-2016 18:20:50 echo "Command 3"
 1049  25-04-2016 18:20:51 echo "Command 4"
 1050  25-04-2016 18:20:53 echo "Command 5"
 1051  25-04-2016 18:20:54 echo "Command 6"
 1052  25-04-2016 18:20:56 echo "Command 7"
 1053  25-04-2016 18:20:57 echo "Command 8"
 1054  25-04-2016 18:21:00 echo "Command 9"
 1055  25-04-2016 18:21:02 echo "Command 10"
 1056  25-04-2016 18:21:07 history 11
[18:21:07 jonathag@gb-slo-svb-0221 ~]$ histdel 1049 1051
[18:21:23 jonathag@gb-slo-svb-0221 ~]$ history 8
 1046  25-04-2016 18:20:47 echo "Command 1"
 1047  25-04-2016 18:20:48 echo "Command 2"
 1048  25-04-2016 18:20:50 echo "Command 3"
 1049  25-04-2016 18:20:56 echo "Command 7"
 1050  25-04-2016 18:20:57 echo "Command 8"
 1051  25-04-2016 18:21:00 echo "Command 9"
 1052  25-04-2016 18:21:02 echo "Command 10"
 1053  25-04-2016 18:21:07 history 11

问题实际上是从历史记录中删除最后 10 个命令,因此如果您想节省一点精力,可以使用另一个函数来调用histdel为您进行计算的函数。

histdeln(){

  # Get the current history number
  n=$(history 1 | awk '{print $1}')

  # Call histdel with the appropriate range
  histdel $(( $n - $1 )) $(( $n - 1 ))
  }

此函数接受 1 个参数,即要删除的先前历史记录项的数量。因此,要从历史记录中删除最后 10 个命令,只需使用histdeln 10.

于 2016-04-25T17:26:06.400 回答
46

使用 Bash 5,您现在可以做一个范围......万岁!:

history -d 511-520

或倒数 10:

history -d -10--1

摘自Bash 5 手册页

'历史'

选项(如果提供)具有以下含义:

'-d OFFSET' 删除位置 OFFSET 的历史条目。如果 OFFSET 为正,则应指定为显示历史记录时出现的值。如果 OFFSET 是负数,它被解释为相对于比最后一个历史位置大一,因此负索引从历史记录的末尾开始计数,并且索引“-1”指的是当前的“历史 -d”命令。

'-d START-END' 删除位置 START 和 END 之间的历史条目,包括端点。START 和 END 的正值和负值按上述解释。

这是我对 Bash 4 的解决方案。它迭代地删除单个条目或从最低索引开始的一系列历史记录。

delHistory () {
    count=$(( ${2:-$1} - $1 ))
    while [[ $count -ge 0 ]]; do
        history -d "$1"
        ((count--))
    done
}

delHistory 511 520
于 2019-01-16T19:38:26.143 回答
31
for x in `seq $1 $2`
do
  history -d $1
done
于 2013-02-07T12:14:07.517 回答
22

首先,键入:history并写下您要删除的行号序列。

要清除从 1800 到 1815 行的行,请在终端中写入以下内容:

$ for line in $(seq 1800 1815) ; do history -d 1800; done

如果要删除删除命令的历史记录,请为 1815 = 1816 添加 +1,该序列的历史记录 + 删除命令将被删除。

例如 :

$ for line in $(seq 1800 1816) ; do history -d 1800; done
于 2016-02-26T10:50:49.723 回答
19

结合上面的答案:

history -w vi ~/.bash_history history -r

于 2017-09-21T03:57:31.633 回答
9

编辑:

更改了支撑迭代器,很好的调用。此外,使用反向迭代器调用此函数。

您可能可以执行以下操作:

#!/bin/bash
HISTFILE=~/.bash_history   # if you are running it in a 
                           # non interactive shell history would not work else
set -o history
for i in `seq $1 $2`;
do
    history -d $i
done
history -w

你会在哪里唤起这样的:

./nameOfYourScript 563 514

请注意,我没有对边界进行任何错误检查。我将把它作为练习留给读者。

另见这个问题

于 2013-02-07T12:10:25.430 回答
9

也许对某人有用。
当您登录到当前会话的任何控制台/终端历史记录的任何用户时,仅存在于某些“缓冲区”中,该缓冲区在您注销时刷新到 ~/.bash_history。
因此,为了保密,您可以:
history -r && exit
您将被注销,所有会话的(并且唯一的)历史记录都会被清除;)

于 2017-10-27T12:17:17.920 回答
7

我使用了此线程中共享的解决方案组合来擦除命令历史记录中的跟踪。首先,我验证了保存命令历史的位置:

echo $HISTFILE

我编辑了历史:

vi <pathToFile>

之后,我使用以下命令刷新当前会话历史缓冲区:

history -r && exit

下次您进入此会话时,您将在命令历史记录中看到的最后一个命令是您留在pathToFile上的最后一个命令。

于 2018-12-21T15:10:28.280 回答
7

不是直接要求的答案,而是问题的根本原因:

您还可以通过在命令前加上空格字符来阻止命令进入历史记录:

# This command will be in the history
echo Hello world

# This will not
 echo Hello world
于 2020-12-12T08:29:34.303 回答
2

简短但甜蜜:for i in {1..10}; do history -d $(($HISTCMD-11)); done

于 2020-06-03T14:34:19.793 回答
2

删除最后 10 个条目(根据您的示例):

history -d 511 520
于 2018-05-27T12:13:08.470 回答
2
history -d 511;history -d 511;history -d 511;history -d 511;history -d 511;history -d 511;history -d 511;history -d 511;history -d 511;history -d 511;

粗鲁但实用

于 2020-06-17T11:50:41.833 回答
1

我用这个(我有 bash 4):

histrm() {
    local num=${1:- 1}
    builtin history -d $(builtin history | sed -rn '$s/^[^[:digit:]]+([[:digit:]]+)[^[:digit:]].*$/\1/p')
    (( num-- )) && $FUNCNAME $num
    builtin history -w
}

builtin history部分和最后一部分是-w因为我有一个著名技巧的变体来跨终端共享历史,如果没有这些部分,这个功能就会失效。他们确保调用真正的history内置 bash(而不是我自己的包装器),并在删除条目后立即将历史记录写入 HISTFILE。

但是,这将与“正常”历史配置一样工作。

您应该使用要删除的最后条目数来调用它,例如:

histrm 10

将删除最后 10 个条目。

于 2019-02-28T12:27:23.627 回答
1

history -c 将清除所有历史记录。

于 2016-05-02T09:20:42.220 回答
1

我使用此脚本删除历史记录中的最后 10 个命令:

pos=$HISTCMD; start=$(( $pos-11 )); end=$(( $pos-1 )); for i in $(eval echo "{${start}..${end}}"); do history -d $start; done

它使用$HISTCMD环境变量来获取历史索引,并使用它来删除最后 10 个条目history

于 2018-09-11T14:35:10.277 回答
0

尝试以下操作:

for i in {511..520}; do history -d $i; echo "history -d $i"; done
于 2019-01-15T07:55:23.940 回答
0
for h in $(seq $(history | tail -1 | awk '{print $1-N}')  $(history | tail -1 | awk '{print $1}') | tac); do history -d $h; done; history -d $(history | tail -1 | awk '{print $1}')

如果要删除 10 行,只需将 N 的值更改为 10。

于 2016-11-30T15:53:29.993 回答
0

history -darg 取一个范围,$HISTCMD是历史记录中的最大数字。

此函数用于n从历史记录中删除最后的条目(只需传入要删除的历史命令的数量,例如rmhist 5):

$ rmhist()  { history -d $(($HISTCMD - $1))-$HISTCMD ;}

或者.. 使用这样的 arg 来从历史上的某个点(包括)或最后一个“n”命令中删除:

rmhist() { 
  case $1 in 
    --from|from) local start=$2; ;; 
    --last|last) local start=$(($HISTCMD - $2)) ;; 
    *) echo "Try rmhist --from # or rmhist --last n "; return ;; 
  esac; 
  history -d ${start}-${HISTCMD}
}

结果如下所示:

 5778  ls /etc
 5779  ls /tmp
 5780  ls /dev
 5781  ll
 5782  cd /tmp
 5783  cd
 5784  history
(base) ~ $ rmhist --last 3
(base) ~ $ history 5
 5778  ls /etc
 5779  ls /tmp
 5780  ls /dev
 5781  ll
 5782  history 5
(base) ~ $ rmhist --from 5780
(base) ~ $ history 5
 5776  history 10
 5777  ls
 5778  ls /etc
 5779  ls /tmp
 5780  history 5
于 2022-02-16T23:07:15.407 回答
0

一个简单的函数可以按数字杀死所有人(尽管它会出错)

kill_hist() {
    for i in $(echo $@ | sed -e 's/ /\n/g;' | sort -rn | sed -e 's/\n/ /;')
    do
            history -d $i;
    done
}
kill_hist `seq 511 520`
# or kill a few ranges
kill_hist `seq 1001 1010` `seq 1200 1201`
于 2017-05-31T22:34:19.593 回答