Changing how bash behaves

options sasquatch i
Credit: f;ickr / Sasquatch_I

Bash is clearly an excellent shell and one that most Unix users are familiar with, but it may be far more customizable than many of us realize. Ever hear of shopt? It's a built-in that allows you to change how bash deals with command history, sources files, spell checking, and a lot more.

Think of shopt as "shell options". Whether you choose to pronounce shopt as "shop-tee" or "shopped" doesn't matter at all, but knowing how the command works and what it does can come in quite handy every now and then.

Being a built-in means, of course, that you're not going to find shopt with the which command and it won't have its own man page. If you run the command "man shopt" and page through about 50 screens, you'll get a brief introduction to the command and an explanation of the shell options that you can manipulate with it.

For starters, shopt's -s option (without any arguments) will show you which of its settings are currently in force. By default, you'll see something like this:

$ shopt -s
checkwinsize    on
cmdhist         on
expand_aliases  on
extquote        on
force_fignore   on
hostcomplete    on
interactive_comments    on
login_shell     on
progcomp        on
promptvars      on
sourcepath      on

If you want to see the settings which aren't enabled, use shopt -u. And, if you want to see all 40 of them, type just shopt.

$ shopt -u | head -5
autocd          off
cdable_vars     off
cdspell         off
checkhash       off
checkjobs       off

Type shopt followed by any of its possible settings will show you whether that setting is enabled or not.

$ shopt cdspell
cdspell         off

As you can see, one of the settings that you might like to try out, cdspell, is turned off by default. It's one that can help if you frequently misspell pathnames. For example, with this setting enabled, you can get past the transpositions of characters in commands like the one shown below.

$ mkdir mydir/save
$ cd mydir/svae
$ pwd

Type just shopt on the command line, on the other hand, and you'll see a list of all of its various settings whether they're currently in force or not. At least you will if you're using bash or a related shell.

$ shopt | head -10
autocd          off
cdable_vars     off
cdspell         off
checkhash       off
checkjobs       off
checkwinsize    on
cmdhist         on
compat31        off
compat32        off
compat40        off

The cmdhist option is an interesting setting. On by default, if you turn it off, run a multi-line command, and then check your history, you will see something like this:

  849  for file in `ls`
  850  do
  851     echo $file is my favorite file
  852  done
  853  history

Notice what's different here? Each line of the command is stored in a different history line. Normally, a command like this would look like this in our history buffer:

  840  for file in `ls`; do     echo $file is my favorite file; done

If you're setting up a complex "for" line and want to use it to repeat a series of commands, separating the for line like this might make a lot of sense.

To re-enable the setting (i.e., turn it back on), use the shopt -s cmdhist command.

Expanding an alias means using the command that an alias is set to represent so if you set target to be equal to a long pathname e.g., alias target="cd /opt/apps/mapper/current/data/stats/operational/logs" you can use "target" to move into the deeply buried directory. Basically, it allows aliases to be used in place of commands.

If you have the expand_aliases option turned off, on the other hand, this doesn't happen.

$ alias target="cd /opt/apps/mapper/current/data/stats/operational/logs"
$ target
$ pwd
$ cd
$ shopt expand_aliases
expand_aliases  on
$ shopt -u expand_aliases
$ target
-bash: target: command not found

One rather unexpected behavior associated with bash is that, if you source a script without providing a pathname for the script, it will look down your search path before it looks in the current directory.

You can turn off this behavior with the shopt -u sourcepath command. In the example below, we see that sourcing the showmypath script runs the script in the bin directory rather than the one in the current directory if the sourcepath option is set (as it is by default). If that option is turned off, it runs the one in the current directory.

$ source showmypath
$ shopt -u sourcepath
$ source showmypath

The script in this example reports its actual location using the command shown below.


echo "$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

The various settings that you can manipulate using shopt allow you to change the nature of bash. Though the shell's defaults generally mean that the shell will make the most sensible choices, it's useful at times to know what you can change and how.

Join the Network World communities on Facebook and LinkedIn to comment on topics that are top of mind.
Must read: 10 new UI features coming to Windows 10