Как удалить историю последних 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, но как удалить последние 10 команд и историю между 10 командами с помощью одной команды в оболочке?

Можем ли мы написать сценарий bash и выполнить его для удаления истории?

Джастин Джон
источник
18
vi $HISTFILEи удалите то, что хотите. Используйте, head -n -10если вам нужно его автоматизировать.
Антон Коваленко
Это вопрос не по теме ? или Здесь не место задавать подобные вопросы? Если да, то где мне задать этот вопрос, я имею в виду, где в обмене стеками?
Джастин Джон
1
Команды оболочки работают одинаково независимо от того, вошли ли вы в систему локально или через ssh.
Barmar
2
Unix и Linux StackExchange (unix.stackexchange.com), вероятно, лучше подходят для ответа на этот вопрос. Здесь это не по теме, потому что это не относится строго к программированию.
Дэн Молдинг
4
Программирование сценария оболочки - идеальное решение этого вопроса, поэтому его следует рассматривать как связанное с программированием. Не говоря уже о том, что OP действительно запросил сценарий.
SSH Это

Ответы:

109

Вы пробовали редактировать файл истории напрямую:

~/.bash_history
WheretheresaWill
источник
2
@WherethereisaWill OP хотел сценарий, а не ручную настройку.
Тайлер Джандро
10
вступит в силу после перезапуска (закрытия и повторного открытия) терминала
khaled_webdev
8
Если вы сделаете это с помощью vim, вы можете найти свою историю удалений, ~/.viminfoпоэтому обязательно удалите и ее!
Waltwood
5
иногда он сохраняется в памяти, и никакое ручное редактирование не сохраняется после следующего входа в систему ..
superhero
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 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.

JGC
источник
history | tail -1 | awk '{print $1}'можно упростить доhistory 1 | awk '{print $1}'
Джордж Хиллиард
-bash: tac: command not foundна Mac OSX, иначе это был бы лучший ответ.
Зим
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
Barmar
источник
3
Обязательно используйте большее число для первого аргумента, иначе вы удалите все остальные команды. Например, когда команда 511 удалена, все сдвигается вниз, так что 512 становится новым 511, а 513 - новым 512. Таким образом, он history -d 511работает, как ожидалось, затем history -d 512удаляет то, что было 513, и 512 остается в истории как команда 511. Надеюсь, что это имеет смысл ,
Мэтью
5
@ Мэтью Это не обязательно. Я не удаляю $xкаждый раз через цикл, я удаляю $1. Таким образом, он сначала удаляет 511, а 512 становится 511. Затем он снова удаляет 511 и так далее.
Barmar
@Matthew Обратите внимание, что я сделал аналогичный комментарий к ответу Тайлера. Я придумал свое решение как исправление этого.
Barmar
вы правы, в моей спешке, когда я написал это одной строкой в ​​моем приглашении bash, я использовал for i in... history -d $iи получил результаты, описанные в моем комментарии выше. Используя $ 1, это абсолютно правильно, как указано в вашем исходном ответе.
Мэтью
19

С 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
Дэвид Хэтч
источник
18

Сначала введите: historyи запишите последовательность номеров строк, которые вы хотите удалить.

Чтобы очистить строки, скажем, с 1800 по 1815, напишите в терминале следующее:

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

Если вы хотите удалить историю для команды удаления, добавьте +1 для 1815 = 1816 и история для этой последовательности + команда удаления будет удалена.

Например :

$ for line in $(seq 1800 1816) ; do history -d 1800; done
Гассан Зейн
источник
Я сделал обновление, но все еще не работает правильно в Ubuntu 12.04 .. :( Похоже, что часть номера строки работает неправильно
Бинод Калатил
Я отклонил предложение Бинода отредактировать, поскольку это не логическая ошибка. Исходный код Гассана использует тот же подход, что и ответ Бармара - который работает. Комментарии к ответу Бармара объясняют, почему предложение о замене 1800 на $lineудаляет все остальные строки, а затем превышает желаемый диапазон.
Энтони Геохеган
14

Объединяя ответы сверху:

history -w vi ~/.bash_history history -r

Брайант Бернштейн
источник
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 и так далее. Таким образом, будут удалены все остальные строки.
Бармар
Вы не можете включать переменные в раскрытие фигурных скобок.
чепнер
seq 563 514ничего не напечатает. Вам нужно seq 563 -1 514. В качестве альтернативы вы можете просто использовать history -d $1аргументы как514 563
anishsane
9

Может кому будет полезно.
Когда вы входите в систему с любым пользователем любой консоли / терминала, история вашего текущего сеанса существует только в некотором «буфере», который сбрасывается в ~ / .bash_history при вашем выходе из системы.
Итак, чтобы сохранить все в секрете, вы можете просто:
history -r && exit
и вы выйдете из системы с очищенной (и только) историей вашего сеанса;)

Alex
источник
5

Я использовал комбинацию решений, представленных в этом потоке, чтобы стереть след в истории команд. Во-первых, я проверил, где хранится история команд:

echo $HISTFILE

Я редактировал историю с помощью:

vi <pathToFile>

После этого я очищаю буфер истории текущего сеанса с помощью:

history -r && exit

В следующий раз, когда вы войдете в этот сеанс, последняя команда, которую вы увидите в истории команд, будет последней, которую вы оставили в pathToFile .

М. Глерия
источник
это работает для меня, для ответа от @jgc, когда я снова вхожу на сервер, история снова возвращается, работает только для этого сеанса, вошедшего в систему
Йогешвар Танвар
1

history -c очистит все истории.

user6280539
источник
1

чтобы удалить последние 10 записей (на основе вашего примера):

history -d 511 520
ThePhilosopher
источник
1
В GNU bash версии 4.3.11 (1) удаляется только первая строка в списке
Гэри
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.

Junaid
источник
1

Попробуйте следующее:

for i in {511..520}; do history -d $i; echo "history -d $i"; done
rb1234
источник
Это предполагает, что он уже перечислил историю и заранее знает все идентификаторы
Маркоорн
и он не может быть последним в списке истории, в противном случае: «позиция в истории вне допустимого диапазона»
devwebcl
это должно быть: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;

Грубый, но функциональный

Daddef
источник
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`
steveo'america
источник
0

Коротко, но мило: for i in {1..10}; do history -d $(($HISTCMD-11)); done

алхимия
источник