Удалить определенную строку из файла истории Bash

Ответы:

109

Вам необходимо выйти из системы и снова войти в нее или запустить, history -aчтобы текущая история была сохранена на диске.

Тогда просто отредактируйте файл ~/.bash_history.

Кир
источник
19
Если установлена ​​переменная окружения HISTFILE, файл истории - это не ~ / .bash_history, а $ {HISTFILE}.
Каролос
20
Записи записываются в файл истории при выходе из оболочки. Поэтому после ввода команды, которую вы хотите удалить, вам необходимо либо выйти из системы и снова войти в нее, либо использовать «history -d xxxx», чтобы удалить их из текущего сеанса оболочки.
вредно
3
но как бы вы удалили запись редактирования файла истории?
чилиNUT
5
@chiliNUT: просто начните свою команду (например vim ~/.bash_history) с пробела; Команды, начинающиеся с пробела, обычно не регистрируются (см. $HISTCONTROL).
cYrus
Я не думаю, что это так в моем дистрибутиве, но в целом это имеет смысл
chiliNUT
149

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

  1. Ввод history -d <line_number>удаляет указанную строку из истории в памяти.
  2. Набор текста history -wзаписывает текущую историю в памяти в ~/.bash_historyфайл.

Два шага вместе навсегда удаляют строку из истории в памяти, а также из файла .bash_history .

Бумажный фонарь
источник
7
как удалить последнее history -wиз истории?
KrIsHnA
@KrIsHnA править ~ / .bash_history вручную
Александр Мышов
5
Или добавьте пробел перед ним, чтобы предотвратить его добавление, как в ответе @ tao
Марк
Чтобы найти <line_number>просто history | grep [unwanted_content]получить список со всеми строками, содержащими [unwanted_content](например, пароли).
AvL
Как удалить несколько (определенных) строк (по идентификатору)?
Патрос
39

Чтобы предотвратить добавление команды в историю в первую очередь, убедитесь, что переменная окружения HISTCONTROLсодержит среди значений, разделенных двоеточиями, значение ignorespace, например (добавьте, например, в .bashrc):

$ export HISTCONTROL=ignorespace

Это предотвратит добавление в историю любой команды с начальным пробелом. Затем вы можете полностью очистить историю, запустив

$  history -c -w
  ^-- additional space character
дао
источник
32

Прежде всего, если команда, которую вы собираетесь выдать, чувствительна, небезопасна или вам просто не нужно, чтобы она загромождала вашу историю, лучше всего / быстрее всего просто предотвратить ее попадание в историю. Убедитесь, что $HISTCONTROLсодержит ignorespace:

(bash)$ echo $HISTCONTROL
ignoredups:ignorespace

Затем выполните любую команду, которую вы не хотите в своей истории, пробелом:

(bash)$  sensitive-cmd-with --password 82cf7dfe
(bash)$  rm -r... # One-off recursive remove; mustn't be accidentally repeated!

Если вы случайно поместили нежелательную команду в историю, при условии, что ваша сессия bash все еще открыта, команда еще не коснулась диска. Чтобы удалить предыдущую команду в истории, выполните:

(bash)$  history -d $((HISTCMD-1))

Обратите внимание на ведущий пробел; эта команда требует ignorespace, иначе она просто удалит себя!

Если вы хотите удалить последние несколько команд, найдите последний и первый номер истории:

(bash)$  history 5
  598  ok
  599  sensitive
  600  unsafe
  601  doesn\'t-work
  602  otherwise-unwanted

В этом случае 602 и 599. Тогда выдайте:

(bash)$  for i in {602..599}; do history -d $i; done

(Без ignorespaceэтого было бы 603..599.)

Если вы не хотите, чтобы какая-либо история из вашего текущего сеанса попала на диск, выйдите, используя:

(bash)$ kill -9 $$

До сих пор подход заключается в том, чтобы даже не допустить записи чувствительных элементов истории на диск для дополнительной безопасности, потому что теоретически данные, удаленные с энергонезависимого носителя, все еще могут быть восстановлены.

Однако, если команды, которые вы хотите удалить, относятся к предыдущему сеансу, они уже будут добавлены при $HISTFILEвыходе. Манипулирование истории с вышеупомянутыми командами будет еще только добавить остальные новые детали к $HISTFILE, на выходе . Для того, чтобы перезаписать$HISTFILE с учетом текущей сессии по всей истории, прямо сейчас , вопрос:

(bash)$  history -w

Конечно, для элементов истории, уже находящихся на диске, альтернативой редактированию истории с history -dпоследующими командами history -wявляется редактирование $HISTFILEс помощью текстового редактора.

Джеймс Хей
источник
1
«Манипулирование истории с вышеупомянутыми командами будет еще только добавить остальные новые детали к $HISTFILE, на выходе .» На самом деле, это не совсем верно. Кажется, он только добавляет оставшиеся новые элементы, которые «выпирают» из первоначальной длины истории. Например, если я удаляю 5 оригинальных предметов и добавляю 15 новых, добавляются только последние 10 новых, тогда как я ожидаю, что все 15 новых будут добавлены. Я думаю, что это ошибка, потому что я не вижу, как это всегда желательно функциональность.
Джеймс Хей
1
Я думаю, Bash принимает к сведению оригинальную длину. При закрытии сеанса он предположительно добавляет элементы, число которых превышает это значение. Если это значение уменьшалось каждый раз при удалении элемента, число которого меньше или равно этому значению, оно будет работать так, как ожидается. ;-)
Джеймс Хай
15

Несколько техник:

Предотвращение сохранения конфиденциальной информации в файле истории

Если вы ввели какой-либо пароль в командной строке, а затем понимаете, что все команды записываются в журнал, вы можете:

  1. Принудительно завершить текущий сеанс без сохранения истории:

     kill -9 $$

    Это отбросит всю текущую историю.

  2. Набирайте ↑ (up arrow)в сеансе open bash, пока не будет отображена конфиденциальная информация, затем с помощью клавиш редактирования строки, таких как Ctrl+, Wудалите конфиденциальную информацию, а затем ↓ (down arrow) до появления новой пустой строки перед вводом Enter.

Удалить конфиденциальную информацию из файла истории

Если вы понимаете, что конфиденциальная информация уже сохранена, и вы хотите удалить ее, но не всю свою историю:

Простая sedкоманда может сделать работу:

sed -e '/SeNsItIvE InFo/d' -i .bash_history

но, когда вы вводите это, вы создаете другую строку истории, содержащую шаблон поиска (конфиденциальную информацию), который вы пытаетесь удалить. Чтобы вы могли:

sed -e "/$(head -n1)/d" -i .bash_history

Это будет работать head -n1с вводом с терминала. Похоже, что ваш терминал завис (не будет подсказки); просто введите информацию, которую вы хотите удалить из файла. Это хитрость, позволяющая вводить (часть) команды без фактического ее ввода в командной строке, что делает ее непригодной для включения в запись истории. Затем sedбудет использовать введенный вами текст для поиска .bash_history и удаления всех строк, содержащих конфиденциальную информацию. Примечание: если ваш шаблон конфиденциальной информации содержит косую черту (ы), вы должны экранировать их обратной косой чертой или изменить sedкоманду, чтобы использовать этот синтаксис для указания разделителя, который не появляется в шаблоне:

sed -e "\|$(head -n1)|d" -i .bash_history

Другим способом может быть удаление только конфиденциальной информации, но сохранение команд, содержащих эту информацию. Для этого вы можете просто заменить конфиденциальную информацию заменой текста на ваш выбор:

sed -e "s/$(head -n1)/Santa Claus/g" -i .bash_history.

Удалить конфиденциальную информацию из любого файла в определенном дереве

Наконец, чтобы быть уверенным, что это не останется в другом забытом файле:

SENSITIVEINFO="$(head -n1)"
find . -type f -print0 | xargs -0 grep -l "$SENSITIVEINFO"

перечислит все заинтересованные файлы.

find . -type f -print0 |
    xargs -0 grep -l "$SENSITIVEINFO" |
    tr \\n \\0 |
    xargs -0 sed -e "s/$SENSITIVEINFO/Santa Claus/g" -i

заменит все вхождения конфиденциальной информации во всех файлах в дереве каталогов с корнем в .. Примечание: даже если эта команда использует xargs -0, она не будет обрабатывать файлы с символами новой строки в их именах.

Ф. Хаури
источник
11

Найдите строку, которую хотите удалить, нажимая, ↑ (up arrow)пока она не появится, затем нажмите Ctrl+ U. Это должно удалить линию.

Если вы используете historyкоманду, вы увидите, что строка заменена звездочкой.

vicentecarro
источник
2
На самом деле, я считаю, что вы должны навести курсор на строку, нажать Ctrl + U, а затем навести курсор вверх или вниз на другую строку (возможно, пустую в нижней части списка). Кроме того, строго говоря, строка не была заменена звездочкой. Скорее команда была стерта, а номер истории был добавлен с *.
G-Man
1
Это становится намного более мощным с Ctrl + R (обратный инкрементальный поиск в истории), затем, например, [End], Ctrl + U
sehe
4

Если вам нужно удалить несколько строк одновременно, я обычно использую это:

history | grep <string> | cut -d ' ' -f 3 | awk '{print "history -d " $1}'

Если вам нужно удалить последнюю команду, которую вы можете использовать:

history -d $((HISTCMD-2))
облигация
источник
2
Это выглядело, как будто это сработало, но history | grep <string>все равно показывает все строки, которые, как он утверждал, удалял ...
Брок Хенсли,
1
Это удалит неправильные строки истории после удаления первой!
mivk
1
Но, к счастью, он печатает только неправильные команды удаления. Следующее выведет правильные команды удаления:history | grep XYZ | grep -v grep | tac | awk '{print "history -d", $1}'
mivk
3

Если вам нужно удалить ряд строк из истории, следующая функция bash может сэкономить вам некоторое время:

function histdel() {
    [ $# -eq 1 ] && history -d "$1" && history -w
    if [ $# -eq 2 -a "$1" -le "$2" ]; then
        for n in `seq "$2" "$1"`; do
            history -d "$n"
        done
        history -w
    fi
}

Функция обычно должна быть добавлена ​​к $HOME/.bashrc. Чтобы использовать эту функцию немедленно, вам понадобится снова прочитать файл с помощью запущенной оболочки ( . $HOME/.bashrc). Затем удалить, например, команды 200-210 из истории:

$ histdel 200 210

(Примечание. Этот вопрос входит в число самых популярных результатов поиска, если вы ищете удаление ряда команд из истории bash. Поэтому, хотя приведенное выше - больше, чем задает вопрос, оно может быть полезно для некоторых читателей.)

M000
источник
3
Альтернативные формы для forзаявления: for n in $(seq "$2" "$1")некоторые стилистически предпочитают, и, если seqне работает, попробуйте for ((n="$2"; n>="$1"; n--)).
Скотт
3
history | sed -i 59d

59 это номер строки. Не может быть ничего слаще этого :)

KroKite
источник
3

Просто попробуйте это,

$ history

это будет отображать идентификатор истории и команды, например,

,
,
211 ls
212 javac Welcome.java
213 java добро пожаловать
.
,

использовать,

$ history -d 211

Здесь 211 - идентификатор истории. Теперь проверьте это с помощью

$ history

,
,
211 javac Welcome.java
212 java добро пожаловать
.
,

user3378188
источник
2

Я знаю, что прошло много времени с тех пор, как на этот вопрос был задан и дан ответ, но я покажу вам мой метод очистки файла истории и выхода из системы одновременно.

Я бегу : history -w && nano "${HISTFILE}" && history -c && exit

То, что он делает, просто:

  1. history -w : пишет кэшированную историю внутри "${HISTFILE}"
  2. nano "${HISTFILE}"Позвольте мне отредактировать "${HISTFILE}"Вы можете использовать скрипт Sed или что угодно, чтобы очистить свой"${HISTFILE}"
  3. history -c : очистить кэшированную историю, поэтому последняя команда не добавляется.
  4. exit : выйти из системы, добавив кешированную историю ... но она пуста;)

После этой команды вы выйдете с чистым файлом истории. Войдите, чтобы проверить свою историю;)

Надеюсь, это кому-нибудь поможет.

ncenerar
источник
1

Вы также можете редактировать файл истории напрямую, например, nano .bash_historyесли вы находитесь в оболочке bash?

душка
источник