Eight Obscure Bash Options You Might Want to Know About

Some bash options are well known, and well-used. For example, many people put

set -o xtrace

at the top of their scripts to debug them,

set -o errexit

to exit on error, or

set -o errunset

to exit if a variable is referenced but not set.

But there are many other options you can set. Many of them can seem confusing if you read the man page, so I’ve collected some of the ones I think are more useful here and explained them further.

If you are using a Mac, then you may be running
an older version of bash (3.x rather than 4.x)

that does not have all these
options available. If so, see here or here.

set vs shopt?

There are two ways to set bash options from within scripts or on the command line. You can use the set builtin command, or the shopt builtin command. They both manipulate the behaviour of the shell, and differ in their lineage. The set options are inherited, or borrowed, from other shells’ options, while the shopt ones were originated in bash.

If you want to see how your current settings look, then run:

$ set -o
$ shopt

To switch on a setting using set, you can use the long version, or a shorter flag that is equivalent. For example:

$ set -o errunset
$ set -e

both have the same effect.

To switch off a setting using set, you use + instead of -:

$ set +e

For a long time I couldn’t remember which way round it goes, as the logic of (- = on), and (+ = off) seems wrong to me.

To switch on and off a shopt setting, you use the (more logical)-s (set) and -u (unset) flags:

$ shopt -s cdspell # <= on
$ shopt -u cdspell # <= off

Changing Directories

There are a few options that can help dealing with directories.

1. cdspell

If you set this up, then bash will work around your mis-spellings and go to the folder you were going for anyway.

$ shopt -s cdspell
$ mkdir abcdefg
$ cd abcdeg
$ cd ..

I’ve used this for years, and very occasionally (maybe once a year) it will make a decision that surprises me. But it probably proves useful at least once a day.

2. autocd

If the inefficiency of typing cd is something you can’t bear, then you can set this option to move to folder if the command doesn’t exist.

$ shopt -s autocd
$ abcdefg
$ cd ..

You can also use it in conjunction with autocompletion to quickly hop around:

$ ./abc[TAB][RETURN]
cd -- ./abcdefg

Just don’t call a folder ‘rm -rf *‘ (yes, you can, by the way).

3. direxpand

This is a neat option that gets the shell to perform any expansions of variables, tildes and the like right there for you in the command line if you tab to complete:

$ shopt -s direxpand
$ ./[TAB] # is replaced by...
$ /full/path/to/current_working_folder
$ ~/[TAB] # is replaced by...
$ /full/path/to/home/folder
$ $HOME/[TAB] # is replaced by
$ /full/path/to/home/folder

A Clean Exit

4. checkjobs

This option stops the shell session from exiting if there are any jobs running in the background that haven’t finished yet.

Instead, the unfinished jobs are listed for you. If you still want to exit, you can if you enter exit immediately afterwards again.

$ shopt -s checkjobs
$ echo $$
68125 # <= Process ID of the shell
$ sleep 999 &
$ exit
There are running jobs.
[1]+  Running                 sleep 999 &
$ echo $$
68125 # <= Process ID of the shell is the same
$ exit
There are running jobs.
[1]+  Running                 sleep 999 &
$ exit
$ echo $$
$ 59316 # <= Process ID has changed this time

Globbing Superpowers

5. globstar

This option gives you globbing superpowers! If you type:

$ shopt -s globstar
$ ls **

then the shell will output recursively all folders and subfolders.

Combined with direxpand, you can quickly page through all the files and subfolders beneath you:

$ shopt -s direxpand
$ ls **[TAB][TAB]
Display all 2033 possibilities? (y or n)

6. extglob

This option gives your globbing powers more commonly associated with full-on regular expressions. Occasionally, this is very useful, as it allows you to do nifty things like this:

$ shopt -s extglob
$ touch afile bfile cfile
$ ls
afile bfile cfile
$ ls ?(a*|b*)
afile bfile
$ ls !(a*|b*)

where the patterns are placed in parentheses, separated by pipes, and the operators available are:

? = match zero or one occurences of the patterns given
! = match anything that doesn't match any patterns given
* = zero or more occurences
+ = one or more occurrences
@ = exactly one occurence


7. histverify

If you’re accident prone, then using the history shortcuts like !! and !$ can be scary, especially when you’re just learning them.

The histverify option allows you to see how bash interprets the command before it actually gets run:

$ shopt -s histverify
$ echo !$ # <= On hitting return, command is not run
$ echo histverify # <= Command is redisplayed ready to run
histverify # <= command gets run

This is based on some of the contents of my book Learn Bash the Hard Way, available at $6.99.


8. Noclobber

Again, if you’re accident-prone, you might want to set this one up.

Clobbering is the act of overwriting a file that already exists with the redirect operator (>). This can be disastrous if you’ve not got the file backed up anywhere else.

Using set -C prevents this from happening when you use the redirect operator. If you are sure you want to clobber, you can override with the >| operator instead:

$ touch afile
$ set -C
$ echo something > afile
-bash: afile: cannot overwrite existing file
$ echo something >| afile

If you like this, you might like one of my books:
Learn Bash the Hard Way

Learn Git the Hard Way
Learn Terraform the Hard Way


Get 39% off Docker in Practice with the code: 39miell2

7 thoughts on “Eight Obscure Bash Options You Might Want to Know About

  1. Here’s another useful one for the Changing Directories sections:

    export CDPATH=.:/some/frequently/visited/path:/tmp:

    Now, you can magically cd into any of the directories in the CDPATH variable without having to specify the full path ! This variable is also honored when showing up matches with tab completion (if you use bash-completion).

    For example, if you have a directory ‘~/src’ where all your projects live, add CDPATH=.:${HOME}/src to your bashrc and then you can simply do a ‘cd my_project’ to cd into it !

    Remember tho’ to add the ‘.’ as the first component …think about it :-)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.