7

I have a simple bash script called foo.sh like this:

#!/bin/bash

echo "Foo!"

When I run it as ./foo.sh I get the Foo! message and everything's fine. But if I echo "Foo!" directly from the console, then I obtain the expected behavior and message: bash: !": event not found.

I understand that the ! is presented as a previous command and if used inside p.e. single quotes, then it's considered as a literal. I'm just wondering what is the difference here that running a script with that echo "Foo!" (even with source ./foo.sh works but directly from the console it doesn't.

pangas
  • 73
  • I guess technically, this actually isn't a duplicate of any earlier ones, since on closer look, they don't exactly mention that history expansion is only enabled by default on interactive shells, not in scripts. Argh. – ilkkachu Apr 07 '21 at 13:21
  • Also, btw, newer versions of Bash (4.4 or so) don't trigger history expansion for cases like "foo!", where the bang is at the end of a quoted string. – ilkkachu Apr 07 '21 at 13:35
  • You mean that it's not enabled in the interactive shell by default? – pangas Apr 07 '21 at 14:11
  • 1
    @pangas, I mean that history expansion is enabled by default in an interactive Bash. And disabled by default in a non-interactive one. I don't think that's different between Bash versions. But there's variation between versions with "foo!" and maybe some other similar ones. – ilkkachu Apr 07 '21 at 22:52

1 Answers1

12

By default, interactive bash shells have history expansion enabled (which is what controls the behaviour of !). Sourced files (which exist largely outside of the concept of history expansion) and scripts do not. From man bash (or the online manual):

set [--abefhkmnptuvxBCEHPT] [-o option-name] [arg ...]
-H: Enable ! style history substitution. This option is on by default when the shell is interactive.

This behaviour can be adjusted manually with set [+-]H, or set [+-]o histexpand, where -H/-o enables history expansion, and +H/+o disables it.

See also e.g.:

ilkkachu
  • 138,973
Chris Down
  • 125,559
  • 25
  • 270
  • 266