1

I'm making frequent changes to a bash script and everytime doing "./demo_script.sh" is repetitive.

Is there any way that it can automatically execute as soon as I hit CTRL+ S on keyboard?

lousycoder
  • 119
  • 4

2 Answers2

2

Why not just do !./demo_script.sh, or !./demo, or !./, or any other shortcut? Or perhaps even !.? You should also look at !!.

They all look at the contents of the history buffer.

The !! just asks the shell to re-execute the last command.

The others asks the shell to execute the last command which starts with those characters given.

The CTRL-S is special as it sends the stop signal to the running command, which if you do it to the shell, means it becomes suspended until you release it with CTRL-Q.

You will find all CTRL-<KEY> are rather special in some way and you really should not interfere with them.

Bob Goddard
  • 1,482
2

It is possible but not as straightforward as you probably wish.


Preliminary notes

  • You tagged and you mentioned "a bash script", but it's not really clear if your interactive shell is Bash. I assume it is.

  • ./demo_script.sh is a relative path. I will use it for terseness. To be able to run the script regardless of the directory you're in, use /full/path/to/demo_script.sh or maybe even (cd /full/path/to && ./demo_script.sh) if needed.


Ctrl+s is special

First of all, Ctrl+s is commonly used to stop (pause) the output. It tells the terminal to stop passing data the currently running command (or the shell, or anything) wants to write to the terminal. The command may continue, it is unaware, nothing changes until it tries to write something. If it tries to write something then it will block or notice.

If your terminal is configured so Ctrl+s works this way, then Ctrl+s won't get to whatever program is running. Programs that do want to use Ctrl+s may reconfigure the terminal (and probably restore previous settings just before exiting).

Run stty -a | grep 'stop =' and you will most likely see (among other things) stop = ^S; which means Ctrl+s works as described above.

Either choose another combination, or tell the terminal not to capture Ctrl+s. I assume you really want to use Ctrl+s. This is how you tell the terminal not to capture it:

stty stop ''

Now you can tell your interactive shell to react to Ctrl+s. Keep reading.


Executing command upon keystroke

To tell an interactive Bash to run ./demo_script.sh when it reads ^S from the terminal, invoke this:

bind -x '"\C-s":"./demo_script.sh"'

This is the simplest way as bind -x is designed to run a command. Still it may misbehave. The problem is if you run a command this way then it will find the terminal with settings (imposed by Bash) appropriate for when Bash reads a command. These settings are different than settings appropriate for when Bash runs a command. Bash changes the terminal settings back and forth exactly because settings appropriate for and expected by scripts and commands are not what Bash wants when it shows you the prompt and lets you type and edit a command line.

Your ./demo_script.sh will find the terminal with unexpected settings. This may result in mishandled (mangled or even missing) terminal output and/or input.

If the script changes the settings of the terminal and doesn't change them back then in turn Bash will find unexpected settings after the script exits.

In other words, in case of a command started from bind -x Bash neither configures the terminal for the command, nor it configures the terminal back for itself.


Generating keystrokes upon keystroke

If the described behavior is a problem, consider the following binding (instead of the above one):

bind '"\C-s":"\C-u ./demo_script.sh\C-j"'

This will make Bash react to Ctrl+s by

  • "typing" Ctrl+u as if you hit it;

    (this combination is bound to unix-line-discard by default, I assume you did not change it, I used it in case you press Ctrl+s when the command line is not empty;)

  • then "typing" ./demo_script.sh as if you typed it;

    (the leading space will prevent Bash from saving the command to history; remove the space if you wish;)

  • and then "typing" Ctrl+j as if you hit Enter.

This variant injects keystrokes. Bash will behave as if you typed all these, so it will properly configure the terminal for the command and (after the command finishes) again for itself.