When one issues the set command without arguments at a bash prompt (which should output a list of shell variables and their values), a script of 8,274 lines scrolls by. Examining this script shows that it is instructions to the shell for executing commands - and it seems that it runs python scripts, making it essentially a kludge of monstrous proportions. I've seen other builtins behave in a few ways

No output:

Me:~$ wait
Me:~$ true
Me:~$ test

An error, with no usage hint:

Me:~$ select
bash: syntax error near unexpected token `newline'

An error, with usage hint:

Me:~$ source
bash: source: filename argument required
source: usage: source filename [arguments]
Me:~$ return
bash: return: can only `return' from a function or sourced script

I'm having trouble understanding why set behaves in this way. It seems undocumented, and I wasn't really expecting it. I'm troubled as to why this happens. Can anyone explain?


Those 8k lines are mainly completion functions from the bash-completion package. On my old desktop, bash uses almost a second to read through and define all those functions, most of which I never use, so I disable it.

To disable it, edit your ~/.bashrc, locate these three lines near the end, and prepend a # to each of the lines.

if [ -f /etc/bash_completion ] && ! shopt -oq posix; then
    . /etc/bash_completion

Next time you run an interactive bash session, set will only output about 50-100 lines; mostly environment variables and special shell variables.

  • This explains what is going on here. Thank you very much. Running "set" without arguments should display the variables that are "set." – Eric Weir Feb 20 '12 at 20:49
  • @Eric Weir If you only want to see variables set, you can also use declare -p it also shows you what type of variable it is. declare -f shows functions. Run help declare for a quick overview of how to use it and read its output. – geirha Feb 21 '12 at 8:41

From http://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html:

If no options or arguments are supplied, set displays the names and values of all shell variables and functions, sorted according to the current locale, in a format that may be reused as input for setting or resetting the currently-set variables.

The same documentation, but with some examples, can be found at: http://ss64.com/bash/set.html, and the command help set gives a summary of that information.

So the behavior you describe is indeed correct. I agree that it would be nice if there were a --help option; generally when all of man set, apropos set, which set, and whatis set fail to be helpful, I will try to pass --help as an option. Doing so prevents a command from running with unexpected results, as it will either give me a help message, or trigger an error. In this case:

$ set --help
bash: set: --: invalid option
set: usage: set [-abefhkmnptuvxBCHP] [-o option-name] [--] [arg ...]

I find this trick to be a useful failsafe.

I should point out that the first few Google results for "bash set" led me to this documentation.

  • Thanks for answering. There is a help option, as you say; it's "help set". Otherwise, I think you did not understand the issue, because I'm not sure what your proposed answer is. No, the behavior I described is not correct; see the answer from geirha. – Eric Weir Feb 20 '12 at 20:51
  • The way I read your post, you had three 'questions': (1) "It seems undocumented", which I took as an implicit version of the question "Why isn't this documented / where is this documented?" (2) "It is an unexpected result", which I took as an implicit version of the question "Is this an unexpected result" and (3) "I seem not to like it", which is not a question at all. Phoenix answered the first two as best he could given your ambiguity. – Huckle Feb 20 '12 at 23:48
  • Also, they behavior you described is perfectly correct. As per his first link. – Huckle Feb 20 '12 at 23:52

Try running set | more and watch near the bottom of the first screen. You'll likely see something like this:

__expand_tilde_by_ref ()
    if [ "${!1:0:1}" = "~" ]; then
        if [ "${!1}" != "${!1//\/}" ]; then
...output truncated...       

so the script your are referring to is a cleverly (if not clearly) escaped shell variable. As for wait,test, and true. Those are all documented with man pages. Issue man <command> to find out more about them. Blank output is the expected result of those functions.

  • Thanks for answering. I don't think so. Running "set |more" does not turn the output into a shell variable. And by the way, did you try "man wait" yourself? You do not get the bash shell command "wait" when you do. – Eric Weir Feb 20 '12 at 20:47
  • I actually didn't try wait, I tried test and true because I happened to know they were both builtins. Seems wait is not, but that should have been apparent because man wait yields an entry from section 2 (system calls), which is why which wait returns nothing. – Huckle Feb 20 '12 at 23:45
  • Also, I didn't say it turns the output into a shell variable, I said that output of set happens to contain a script. – Huckle Feb 21 '12 at 0:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.