Почему я могу изменить историю bash?

Почему bash меняет историю, даже если я не выполняю команду, которую я изменяю? Например, если я набираю:

 $ echo foo1 foo1 $ echo foo2 foo2 $ echo foo3 foo3 

После этого я дважды echo foo2 в подсказке я получаю echo foo2 . Я echo foo22 2 и получаю echo foo22 . Теперь вернемся к концу (пустая строка) вниз . Если я сейчас ищу историю, я увижу echo foo22 хотя я никогда не выполнял эту команду!

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

Мне бы хотелось, чтобы история работала так:

  1. Только исполняемые команды сохраняются в истории.

  2. История неизменна. (Если явно не очищено.)

Есть ли способ сделать это?

Изменить – этот вопрос кажется связанным: есть ли способ отменить модификацию истории bash?

  • timestamp сохраненный файл истории
  • Список команд в истории оболочки в порядке их времени окончания?
  • повторная замена расширения истории bash для всех матчей
  • Как сохранить историю командной строки без выхода из системы?
  • Не теряйте текущую команду, когда вверх нажата кнопка в терминале
  • Дубликаты в истории bash
  • Bash: отфильтровать недействительные команды из истории, в частности пароли
  • Могу ли я удалить .bash_history без sudo?
  • 2 Solutions collect form web for “Почему я могу изменить историю bash?”

    Я нахожу все это очень запутанным, контр-интуитивным и раздражающим.

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

    Однако, как и в Bash, это редактирование истории сохраняется только в истории, когда вы перемещаетесь от измененной строки. Нет, если вы отредактируете строку, а затем повторно отправьте ее в виде новой команды, не отпуская ее от нее! В этом специальном случае изменения не сохраняются в истории, потому что они сохраняются как новая запись истории.

    Существует рифма и причина!

    1. Было бы явно противоречить интуиции и раздражать, чтобы не разрешать редактировать историю, прежде чем отправлять ее в качестве новой команды.

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

    Возможным решением может быть следующее: когда пользователь редактирует строку истории, сохраните ее во временной области, представляющей новую строку, которую нужно отправить (и не обновляйте историю). Однако:

    1. Это все равно противоречиво и раздражало бы. Пользователь не сможет редактировать строку, дважды нажмите стрелку вверх, чтобы посмотреть предыдущую строку, а затем дважды стрелку вниз, чтобы вернуться к редактированию. Затем пользователь увидит исходную неотредактированную строку и должен полностью перейти к началу истории, чтобы найти новую версию строки в текущем («ноль истории») буфере редактирования.

    2. Что делать, если пользователь внес два изменения в две разные строки истории? Было бы раздражать, если бы последнее последнее такое редактирование было тихо забито последним.

    Единственный способ иметь неизменную историю, в которой вы можете сделать несколько временных изменений одновременно, и представить их в виде новых команд в любом порядке, вероятно, будет трудно представить в текущей парадигме пользовательского интерфейса, не запутывая. Эта «текущая парадигма UI» заключается в том, что вся рабочая область (история плюс новая запись) отображается на одно окно редактирования на экране с представлением, если таковое имеется, любой визуальной подсказки о том, где находится пользователь, и какой-либо индикации состояния.

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

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

    Оставляя эти изменения, может быть полезно, если причина, по которой вы отказались от изменения этой строки, состоит в том, что сначала вам нужно было сделать что-то еще, и это может быть оригинальное оправдание для этого. Тем не менее, переопределение исходной записи истории плохой ИМО, поскольку вы теряете доказательства того, что вы делали раньше.

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

    Кроме того, даже если вы намереваетесь сохранить эти изменения, если вы хотите вернуться к этой измененной строке, вам нужно снова ее искать.

    Поведение zsh более полезно ИМО. Вы можете изменить всю историю до тех пор, пока вы не принимаете строку, и переходите туда и обратно между вашими измененными строками, но как только вы принимаете новую строку, она добавляется в историю, но старые строки истории сохраняются (при нажатии Ctrl + C отменяет все изменения без добавления новой строки в историю).

    И если вы хотите сохранить изменения, сделанные вами в разных строках, вы должны сохранить строку в очереди с помощью Alt + Q (верхняя часть которой автоматически вытягивается в следующем приглашении) или сохранить ее в kill с помощью Ctrl + U.

    К счастью, в bash / readline вы можете изменить поведение с помощью

     bind 'set revert-all-at-newline on' 

    (или set revert-all-at-newline on в ~/.inputrc чтобы он применим ко всем приложениям с использованием readline).

    Затем вы получите аналогичное поведение, как в yash , то же самое, что и zsh но без очереди ожидания (но вы все равно можете использовать killring (вытащил с Ctrl + Y , Alt + Y )).

    Linux и Unix - лучшая ОС в мире.