Bash – Prompt for confirmation for every command

bashinteractivepromptshell-script

I'm writing a pretty ad-hoc install script for some thing. No much control constructs, basically just a list of commands. I'd like the user to confirm each command before it gets executed. Is there a way to let bash do that, without prefixing every command with a shell function name?

Best Answer

You could use extdebug:

shopt -s extdebug
trap '
  read -n1 -p "run \"$BASH_COMMAND\"? " answer <> /dev/tty 1>&0
  echo > /dev/tty
  [[ $answer = [yY] ]]' DEBUG

cmd1
cmd2
...

For reference, the zsh equivalent would be:

TRAPDEBUG() {
  read -q "?run \"$ZSH_DEBUG_CMD\"? " || setopt errexit
  echo > /dev/tty
}
cmd1
cmd2
...

More portably:

run() {
  printf %s "run $*? " > /dev/tty
  read answer < /dev/tty
  case $answer in
    [yY]*) "$@";;
  esac
}
run cmd1
run cmd2
run cmd3 > file

Beware that in cmd3 > file, the file will be truncated even if you say n. So you may want to write it:

run eval 'cmd3 > file'

Or move the eval to the run function as in:

run() {
  printf %s "run $*? " > /dev/tty
  read answer < /dev/tty
  case $answer in
    [yY]*) eval "$@";;
  esac
}
run cmd1
run 'cmd2 "$var"'
run 'cmd3 > file'

Another portable one, but with even more limitations:

xargs -pL1 env << 'EOF'
cmd1 "some arg"
cmd2 'other arg' arg\ 2
ENV_VAR=value cmd3
EOF

It only works for commands (ones found in $PATH), and arguments can only be strings (no variable or any shell structure, though xargs understand some forms of quoting), and you can't have redirections, pipes...