Find out what your UNIX shell’s flags are & then change them
Today we enter the semi-arcane world of your UNIX shell’s flags, the variables that determine how your shell will function for you. I’m focusing on the bash shell, as that’s the one I know best.
You can see your current flags by echoing the $-
variable, as so:
$ echo $-
himBH
So what do those flags mean? You can type in man bash
& search for SHELL BUILTIN COMMANDS
& then, once you’ve found that section, scroll down (or search) for the set
command. There you’ll find all the flags, written in that “kinda-informative-but-kinda-not” man
page style we all know & love. Or you can check out “Table 8-13 bash features” on http://www.informit.com/articles/article.aspx?p=441605&seqNum=8, which does a nicer job explaining things.
Here’s what my flags mean (note that all of these are defaults):
h
: Short for “hashall” (read that “hash all”), this tells bash to remember the locations of commands it has found through querying your PATH.i
: Short for “interactive”, which is good, because this is a shell with which I’m interacting (entering input & getting back output)!1m
: Short for “monitor”, this enables job control in bash (so you can send jobs to the background viabg
, for instance).B
: Short for “braceexpand” (read as “brace expand”), this allows you to use the very efficient brace expansion in bash2.H
: Short for “histexpand” (read as “hist [history] expand”), this is what enables you to re-run a command from your history by prefacing its number with an exclamation point3.
There are several others (by “several” I mean “about 15 or so”), like:
e
: Short for “errexit”, this causes bash to exit as soon as a command fails. Yikes!C
: Short for “noclobber”, this stops you from overwriting files via redirection.4
You can change these flags when you start the shell or after it’s started by using the set
command. Let’s start with everything working like normal:
$ echo $-
himBH
$ history
<snip>
500 ssh moe
501 ssh larry
502 ssh curly
$ !501
ssh larry
Because the H
flag is set, I can re-run a command from history by using the exclamation point. Now I remove that flag (this is a bit confusing, but +
removes the flag, while -
turns it on) & notice what happens:
$ set +H
$ echo $-
himB
$ history
<snip>
500 ssh moe
501 ssh larry
502 ssh curly
$ !501
-bash: !505: command not found
I can still view my history, but I can’t re-run any commands easily since I disabled histexpand
. Bummer. Let’s turn that back on:
$ set -H
$ echo $-
himBH
$ history
<snip>
500 ssh moe
501 ssh larry
502 ssh curly
$ !501
ssh larry
Now I can use the exclamation point again, & all is swell.
One final thing. Instead of echoing $-
, you can quickly see your shell’s current options with a quick set
command:
$ set -o
allexport off
braceexpand on
emacs on
errexit off
errtraceoff
functrace off
hashall on
histexpand on
history on
ignoreeof off
interactive-commentson
keyword off
monitor on
noclobber off
noexec off
noglob off
nolog off
notify off
nounset off
onecmd off
physicaloff
pipefailoff
posix off
privileged off
verbose off
vi off
xtrace off
The only problem is that the flags aren’t listed here, so you have to do your own cross-indexing using the man
page for bash, but it’s still a nice quick way to see what’s on & what’s off. You can also turn flags off & on using these options. So, for instance, to turn off history expansion (“histexpand” above), you’d use set +o histexpand
, & to turn it on you’d use set -o histexpand
. Same thing as set +H
& set -H
, respectively. As with many things UNIX, it’s your choice which syntax to use. You can go with brevity or comprehension—it’s up to you.
-
OK, so how do you “see” a non-interactive shell? Sounds a bit like the observer effect, I know, but we can in fact easily create & view a non-interactive shell in action. Here’s how: create a text file named test.sh & enter into it the following:
#!/bin/bash echo "I'm a shell & here are my flags:" echo $-
Save the file, then make it executable:
$ chmod 755 test.sh
Run it:
$ ./test.sh I'm a shell & here are my flags: hB
See it? The only flags are
h
(“hashall”) &B
(“braceexpand”)—noi
for “interactive”. ↩ -
“Braces” as in “curly braces” as in
{
&}
. An example:$ ls $ mkdir {test1,test2} $ ls test1/ test2/ $ mkdir test{3,4} $ ls test1/ test2/ test3/ test4/
Pretty cool, eh? A great time-saver! ↩
-
For example:
$ history <snip> 500 ssh moe 501 ssh larry 502 ssh curly $ !501 ssh larry
Use
history
to view the commands you’ve previously entered onto your shell, with each prior command numbered, then re-run a previous command by prefacing its number with an exclamation point. ↩ -
By “redirection”, I’m referring to the
>
or>>
command. So, for example:$ echo $- himBH $ echo "Hello" > test $ cat test Hello $ echo "Bonjour" > test $ cat test Bonjour
Now let’s turn on the
noclobber
option & see what happens:$ set -C $ echo $- himBCH $ cat test Bonjour $ echo "Hello" > test -bash: test: cannot overwrite existing file
Stopped in our tracks. Note that we could still delete the file,
cp
another file overtest
, or edit it manually. We just can’t redirect output to that file, a nice safeguard if you’re feeling really paranoid. Now let’s go back to normal & turnnoclobber
off:$ set +C $ echo $- himBH $ cat test Bonjour $ echo "Hello" > test $ cat test Hello