Як видалити історію останніх 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.
Бармар

2
Unix та Linux StackExchange (unix.stackexchange.com), мабуть, є кращим місцем для цього питання. Тут це поза темою, оскільки це не стосується суворо програмування.
Дан Ліплення

4
Програмування сценарію оболонки є ідеальним рішенням цього питання, отже, його слід вважати пов'язаним з програмуванням. Не кажучи вже про те, що ОП насправді просила спеціально сценарій.
SSH Цього

Відповіді:


109

Ви намагалися редагувати файл історії безпосередньо:

~/.bash_history

2
@WherethereisaWill OP хотів сценарій, а не ручне підключення та чуг.
Тайлер Жандро

10
набере чинності після повторного запуску (закриття та повторного відкриття) терміналу
khaled_webdev

8
Якщо ви зробите це з vim, ви можете знайти свою історію видалення, ~/.viminfoтому обов'язково видаліть її!
waltwood

5
іноді це зберігається в пам’яті, і будь-яке ручне редагування не буде зберігатися після наступного входу ..
супергерой

5
@FizerKhan Я маю на увазі, що внесені зміни .bash_historyможуть бути перезаписані тим, що зберігається в пам'яті. Я вважаю це рішення корисним: superuser.com/a/384383/253543
супергерой

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 і видаляється.

Якщо я також хотів видалити команду delete 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, інакше це була б найкраща відповідь.
Зім

for h in $(seq 1006 1008); do history -d 1006; doneце працює в ubuntu 16.04
махфуз

Короткий, але милий: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 тощо.
Бармар

@Matthew Зауважте, що я зробив подібний коментар до відповіді Тайлера. Я придумав своє рішення як виправлення цього.
Бармар

Ви маєте рацію, я поспішав, коли писав це в одному рядку в моєму баш-підказці, який я використав for i in... history -d $iі отримав результати, які я описав у своєму коментарі вище. Використання $ 1 це абсолютно правильно, як зазначено у вашій оригінальній відповіді.
Метью

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 .. :( Схоже, частина номера рядка працює неправильно
Binod Kalathil

Я відхилив запропоновану редакцію Бінода, оскільки це не логічна помилка. Оригінальний код Гассана використовує той самий підхід, що і відповідь Бармара - який працює. У коментарях до відповіді Бармара пояснюється, чому пропозиція замінити 1800 $lineвидаляє кожен інший рядок, а потім перевищує бажаний діапазон.
Ентоні Геоґеган

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 тощо. Таким чином, це видалить усі інші рядки.
Бармар

Ви не можете включати змінні в розширення дужок.
чепнер

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 записів (на основі вашого прикладу):

history -d 511 520

1
У GNU bash, версія 4.3.11 (1), це видаляє лише перший рядок у списку
Gary

1

Я використовую цей скрипт для видалення останніх 10 команд в історії:

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

Він використовує $HISTCMDvar середовище для отримання індексу історії та використовує його для видалення останніх 10 записів у history.


1

Спробуйте наступне:

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

Це передбачає, що він уже перелічив історію і знає всі посвідчення особи заздалегідь
Маркоорн

і він не може бути останнім у списку історії, інакше: "Позиція історії поза діапазоном"
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вбудованого bash (а не до моєї власної обгортки навколо нього), а також записувати історію в 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`

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.