如何删除Shell中最近10条命令的历史记录?


131

命令如下

  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脚本并执行以删除历史记录吗?


17
vi $HISTFILE并删除您想要的。head -n -10如果必须使其自动化,请使用。
安东·科瓦连科

这个问题是题外话吗?还是这不是问这类问题的合适地方?如果是这样,我应该在哪里问这个问题,我的意思是堆栈交换在哪里?
贾斯汀·约翰

1
无论您是本地登录还是通过ssh登录,Shell命令的工作方式都相同。
Barmar

2
Unix和Linux StackExchange(unix.stackexchange.com)可能是解决此问题的更好场所。它不在这里,因为它与编程没有严格关系。
Dan Moulding 2013年

4
对shell脚本进行编程是解决此问题的理想方法,因此应考虑与编程相关。更不用说OP实际上确实要求脚本。
SSH

Answers:


109

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

~/.bash_history

2
@WherethereisaWill OP需要一个脚本,而不是手动的即插即用。
Tyler Jandreau

10
将在重新启动(关闭和重新打开)终端后生效
khaled_webdev 2014年

8
如果使用vim执行此操作,则可能会找到删除历史记录,~/.viminfo因此请确保也将其删除!
waltwood

5
有时它保存在内存中的任何手动编辑不会下次登录..后坚持
超级英雄

5
@FizerKhan我的意思是,所做的更改.bash_history可以被保存在内存中的内容覆盖。我发现此解决方案很有帮助:superuser.com/a/384383/253543
superhero

73

我的答案基于先前的答案,但是增加了反向顺序,以便将历史项从最近删除到最近。

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

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

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

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

您可以使用以下方法(可能有更好的方法):

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


history | tail -1 | awk '{print $1}'可以简化为history 1 | awk '{print $1}'
乔治·希利亚德

-bash: tac: command not found在Mac OSX上,否则这将是最佳答案。
Zim

for h in $(seq 1006 1008); do history -d 1006; done这在ubuntu 16.04中起作用
mahfuz

短暂而甜蜜:for i in {1..10}; do history -d $(($HISTCMD-11)); done
炼金术

30
for x in `seq $1 $2`
do
  history -d $1
done

3
请确保对第一个参数使用更高的数字,否则您将删除所有其他命令。例如,当删除命令511时,所有内容都向下移动,因此512变为新的511,而513成为新的512。因此,history -d 511按预期方式工作,然后history -d 512删除了以前的513,并且512作为命令511保留在历史记录中。希望这有意义。
马修

5
@Matthew没必要。我并不是在$x每次循环中都删除,而是在删除$1。因此,它首先删除511,然后512变为511。然后再次删除511,依此类推。
Barmar 2015年

@Matthew请注意,我对泰勒的回答也有类似的评论。我想出了解决方案来解决此问题。
Barmar 2015年

您是正确的,我匆匆忙忙地在我使用的bash提示中将其写在一行中for i inhistory -d $i并得到了我在上面的评论中描述的结果。使用$ 1,这绝对是正确的,如您的原始答案中所述。
马修

18

首先,输入: 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

我进行了更新,但在Ubuntu 12.04中仍然无法正常工作.. ::(看来行号部分无法正常工作
Binod Kalathil

我拒绝Binod的建议编辑,因为这不是逻辑错误。Ghassan的原始代码使用与Barmar的答案相同的方法-有效。对Barmar答案的评论解释了为什么将1800替换为的建议$line会删除其他每行,然后超出期望的范围。
Anthony Geoghegan

18

使用Bash 5,您现在可以进行一系列操作了……万岁!

history -d 511-520

或倒数10:

history -d -10--1

Bash 5手册页摘录:

'历史'

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

'-d OFFSET'删除位置OFFSET处的历史记录。如果OFFSET为正,则应指定其显示历史记录时显示的值。如果OFFSET为负,则它被解释为相对于上一个历史位置大一个,因此负索引从历史末尾开始倒数,索引“ -1”表示当前的“ history -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


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

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

另见这个问题


6
删除510之后,511变为510,512变为511,依此类推。因此,这将删除所有其他行。
Barmar

括号扩展中不能包含变量。
chepner

seq 563 514将不打印任何内容。你需要seq 563 -1 514。或者,您可以简单地使用history -d $1带以下参数的参数514 563
anishsane

9

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


5

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

echo $HISTFILE

我用以下方式编辑了历史记录:

vi <pathToFile>

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

history -r && exit

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


这对我有用,对于@jgc的答案,当我再次登录服务器时,历史又回来了,仅适用于已登录的会话
Yogeshwar Tanwar


1

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

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

它使用$HISTCMD环境var获取历史记录索引,并使用它删除中的最后10个条目history


1

尝试以下方法:

for i in {511..520}; do history -d $i; echo "history -d $i"; done

假设他已经列出了历史记录并且事先知道了所有ID
Markoorn

并且它不能是历史记录列表中的最新记录,否则:“历史记录位置超出范围”
devwebcl 19/09/24

它必须是:for i in {511..520}; do history -d $i; echo "history -d 511"; done
devwebcl

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内置函数(而不是我自己的包装器),并在删除条目后立即将历史记录写入HISTFILE。

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

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

histrm 10

将删除最后10个条目。


1
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;

蛮横但实用


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。


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`

0

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

history -d 511 520

1
在GNU bash版本4.3.11(1)中,这仅删除列表中的第一行
Gary

0

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.