Запретить выполнение команды после выполнения другой команды

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

Как я могу предотвратить выполнение команды cmd2 после cmd1 .

Например:

 $ tar tf file.tar $ rm !$ 

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

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

Вы просите много общего с общим ответом, но в некоторой степени это можно сделать относительно легко.

Однако у bash есть как минимум два общих механизма, которые могут помочь в решении этого. Вы можете установить переменную PROMPT_COMMAND, и это будет выполнено после всего, что вы запустили в своем приглашении:

 $ PROMPT_COMMAND='echo BOFH says hi!' BOFH says hi! $ man man BOFH says hi! $ 

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

 $ PROMPT_COMMAND='history -a; tail -n1 ~/.bash_history' PROMPT_COMMAND='history -a; tail -n1 ~/.bash_history' $ wc < test.sh | grep . 5 11 63 wc < test.sh | grep . 

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

 $ # define the logic check $ checkSanity() { grep -q "tar *[tf][[:alpha:]]*[tf] " <<< "$@" && echo "be careful, don't delete this"; } checkSanity() { grep -q "tar *[tf][[:alpha:]]*[tf] " <<< "$@" && echo "be careful, don't delete this"; } $ # feed it the last command $ PROMPT_COMMAND='history -a; last=$(tail -n1 ~/.bash_history); checkSanity "$last"' $ # simple test $ tar tf test.sh 2>/dev/null be careful, don't delete this $ tar xf test.sh 2>/dev/null $ 

Конечно, этот подход полезен для предотвращения PEBKAC (особенно, если вы добавляете sleep 3 в конце), но он не может сломать следующую команду самостоятельно.

Если это действительно то, что вы хотите, DEBUG сигнал DEBUG (например, « trap 'echo "I am not deterministic, haha"' DEBUG ), так как он работает заранее. Будьте внимательны при объединении этих двух подходов, поскольку выход / действие будет удвоено:

 $ df /.../ $ trap 'tail -n1 ~/.bash_history' DEBUG df df trap 'tail -n1 ~/.bash_history' DEBUG trap 'tail -n1 ~/.bash_history' DEBUG 

Чтобы заставить ловушку нарушить команду, вам нужно включить extdebug ( shopt -s extdebug ). Вам также не нужно постоянно сохранять и перечитывать историю, но можете проверить $BASH_COMMAND чтобы получить команду для запуска. Тогда вам просто нужно убедиться, что логическая проверка возвращается 1, когда обнаруживает что-то плохое и 0 в противном случае.

  extdebug If set, behavior intended for use by debuggers is enabled: /.../ 2. If the command run by the DEBUG trap returns a non-zero value, the next command is skipped and not executed. $ checkSanity() { if grep -q "tar *[tf][[:alpha:]]*[tf] " <<< "$1"; then echo "be careful, don't delete this"; return 1; fi; } $ trap 'checkSanity "$BASH_COMMAND"' DEBUG $ # simple test $ tar tf test.sh 2>/dev/null be careful, don't delete this $ tar xf test.sh 2>/dev/null $ 

В bash вы можете установить shopt -s histverify который бы остановил историю от расширения и выполнения за один шаг. Здесь выше $ rm !$ Будет расширяться до $ rm file.tar при первом нажатии Enter , позволяя вам проверять или редактировать, прежде чем нажимать Enter еще раз для выполнения.
Более общее решение изменилось бы на территорию «Делайте то, что я имею в виду» , требуя, чтобы программа вторгалась в ваши намерения.

В этом случае вы получите предупреждение об ошибках из команды rm .

В сценариях инициализации оболочки (предполагая bash , так ~/.bashrc ) вы могли бы псевдоним rm либо -i или -I .

 alias rm="rm -i" 

От man 1 rm

  -i prompt before every removal -I prompt once before removing more than three files, or when removing recursively. Less intrusive than -i, while still giving protection against most mistakes 

Ранее обсуждался более общий вопрос: «Как защитить мою систему от себя». Вкратце, обратите внимание на то, что вы делаете , и только запускайте команды как root когда это необходимо.

В вашем конкретном случае я бы сделал:

 tar tf file.tar if [ -f file ]; then # Assuming you meant to extract a file rm -f file.tar else echo "file is missing. Command failed." fi 

Если вы хотите проверить наличие ошибок и запустить только следующую команду, если первое выполнено

 some_command && another_command 

Хотя в вашем конкретном случае вторая команда все равно будет работать, поскольку она не выходила из системы, даже если она не делала то, что вы хотели.