Oils Reference — Chapter Global Shell Options

This chapter describes global shell options in Oils. Some options are from POSIX shell, and some are from bash. We also use options to turn OSH into YSH.

(in progress)

In This Chapter

Errors

These options are from POSIX shell:

nounset -u  
errexit -e
pipefail

These are from bash:

inherit_errexit

Globbing

These options are from POSIX shell:

noglob -f

From bash:

nullglob   failglob   dotglob

From Oils:

dashglob

Some details:

nullglob

When nullglob is on, a glob matching no files expands to no arguments:

shopt -s nullglob
$ echo L *.py R
L R

Without this option, the glob string itself is returned:

$ echo L *.py R  # no Python files in this dir
L *.py R

(This option is from GNU bash.)

dashglob

Do globs return results that start with -? It's on by default in bin/osh, but off when YSH is enabled.

Turning it off prevents a command like rm * from being confused by a file called -rf.

$ touch -- myfile -rf

$ echo *
-rf myfile

$ shopt -u dashglob
$ echo *
myfile

Other Option

noclobber -C  # Redirects can't overwrite files

Debugging

errtrace (-E)

Enable the ERR trap in both shell functions and subshells.

The option is also set -E. It's designed to be compatible with bash.

extdebug

Show more info in when printing functions with declare -f. Used by task-five.sh.

xtrace (-x)

Show execution traces.

This option is also set -x. It's required by POSIX shell.

verbose

Not implemented.

This option is from POSIX shell.

Interactive

These options are from bash.

emacs   vi

Compat

eval_unsafe_arith

Allow dynamically parsed a[$(echo 42)] For bash compatibility.

ignore_flags_not_impl

Suppress failures from unimplemented flags. Example:

shopt --set ignore_flags_not_impl

declare -i foo=2+3  # not evaluated to 5, but doesn't fail either

This option can be useful for "getting past" errors while testing.

ignore_shopt_not_impl

Suppress failures from unimplemented shell options. Example:

shopt --set ignore_shopt_not_impl

shopt --set xpg_echo  # exit with status 0, not 1
                      # this is a bash option that OSH doesn't implement

This option can be useful for "getting past" errors while testing.

Optimize

rewrite_extern

This options enables a transparent rewriting of external commands to builtins.

Currently, these commands may be rewritten, depending on their argv:

These optimizations are sound - they should not affect the behavior of programs on POSIX system.


This option is on by default in OSH and YSH, but it applies only in non-interactive shells. That is, in interactive shells, commands are never rewritten, regardless of the value of rewrite_extern.

Groups

To turn OSH into YSH, we use three option groups. Some of them allow new features, and some disallow old features.

strict:all

Option in this group disallow problematic or confusing shell constructs. The resulting script will still run in another shell.

shopt --set strict:all    # turn on all options
shopt -p strict:all       # print their current state

Parsing options:

  strict_parse_equals     # Disallow '=x' to avoid confusion with '= x'
  strict_parse_slice      # No implicit length for ${a[@]::}
X strict_parse_utf8       # Source code must be valid UTF-8

Runtime options:

  strict_arg_parse        # Disallow additional arguments to some builtins
  strict_argv             # No empty argv
  strict_arith            # Fatal parse errors (on by default)
  strict_array            # Arrays and strings aren't confused
  strict_control_flow     # Disallow misplaced keyword, empty arg
  strict_env_binding      # Prefix bindings must always be env bindings
  strict_errexit          # Disallow code that ignores failure
  strict_nameref          # Trap invalid variable names
  strict_word_eval        # Expose unicode and slicing errors
  strict_tilde            # Tilde subst can result in error
X strict_glob             # Parse the sublanguage more strictly

ysh:upgrade

Options in this group enable new YSH features. It doesn't break existing shell scripts when it's avoidable.

For example, parse_at means that @myarray is now the operation to splice an array. This will break scripts that expect @ to be literal, but you can simply quote it like '@literal' to fix the problem.

shopt --set ysh:upgrade   # turn on all options
shopt -p ysh:upgrade      # print their current state

Details on each option:

  parse_at                   echo @array @[arrayfunc(x, y)]
  parse_brace                if true { ... }; cd ~/src { ... }
  parse_equals               x = 'val' in Caps { } config blocks
  parse_paren                if (x > 0) ...
  parse_proc                 proc p { ... }
  parse_triple_quote         """$x"""  '''x''' (command mode)
  parse_ysh_string           echo r'\' u'\\' b'\\' (command mode)
  parse_ysh_expr_sub         $[] is YSH expression sub, not synonym for $(( ))
  command_sub_errexit        Synchronous errexit check
  process_sub_fail           Analogous to pipefail for process subs
  sigpipe_status_ok          status 141 -> 0 in pipelines
  simple_word_eval           No splitting, static globbing
  xtrace_rich                Hierarchical and process tracing
  no_xtrace_osh              Disable OSH tracing with +
  no_dash_glob               Avoid globbing files like -rf
  env_obj                    Init ENV Obj at startup; use it when starting
                             child processes
  init_ysh_globals           Init ARGV List at startup
  for_loop_frames            YSH can create closures from loop vars
  verbose_errexit            Whether to print detailed errors
  verbose_warn               Print various warnings to stderr

ysh:all

Enable the full YSH language. This includes everything in the ysh:upgrade group and the strict:all group.

shopt --set ysh:all       # turn on all options
shopt -p ysh:all          # print their current state

Details on options that are not in ysh:upgrade and strict:all:

  expand_aliases (-u)     Whether aliases are expanded
  parse_at_all            @ starting any word is an operator
  no_parse_backslash      Disallow bad backslashes in "" and $''
  no_parse_backticks      Disallow `echo hi`
  no_parse_bare_word      Disallow 'case unquoted' 'for x in unquoted'
  no_parse_dbracket       Disallow legacy booleans [[
  no_parse_dollar         Disallow bare $ for \$  (maybe $/d+/)
  no_parse_dparen         Disallow legacy arithmetic ((
  no_parse_ignored        Don't parse redirects that are ignored
  no_parse_osh            No $''  ( )  &   TODO  ${x%prefix}  ${a[@]}  $$
  no_parse_sh_arith       Disallow legacy shell arithmetic
  no_parse_word_join      Disallow pitfall --flag=r'value'
  no_exported             Environ doesn't correspond to exported (-x) vars
  no_init_globals         At startup, don't set vars like PWD, SHELLOPTS
  no_osh_builtins         Disallow OSH builtins like alias, unalias, etc.
  simple_echo             echo doesn't accept -e -n
  simple_eval_builtin     eval takes exactly 1 argument
  simple_test_builtin     test takes 2 or 3 args; use test not [
  simple_trap_builtin     trap doesn't take a code string, etc.
X simple_trap             Function name only

Caveat: Some options only affect shell startup. For example:

YSH Details

opts-redefine

In the interactive shell, you can redefine procs and funcs.

  redefine_source          'source-guard' builtin always returns 0
X redefine_const            Can consts be redefined?

opts-internal

These options are used by the interpreter. You generally shouldn't set them yourself.

_allow_command_sub  To implement strict_errexit, eval_unsafe_arith
_allow_process_sub  To implement strict_errexit
dynamic_scope       To implement proc and func
_no_debug_trap      Used in pipelines in job control shell
_running_trap       To disable strict_errexit
_running_hay        Hay evaluation

Unlinked Descriptions

Here are some descriptions of individual options.

strict_control_flow

Disallow break and continue at the top level, and disallow empty args like return $empty.

strict_tilde

Failed tilde expansions cause hard errors (like zsh) rather than silently evaluating to ~ or ~bad.

strict_nameref

When strict_nameref is set, undefined references produce fatal errors:

declare -n ref
echo $ref  # fatal error, not empty string
ref=x      # fatal error instead of decaying to non-reference

References that don't contain variables also produce hard errors:

declare -n ref='not a var'
echo $ref  # fatal
ref=x      # fatal

no_parse_ignored

For compatibility, OSH will parse some constructs it doesn't execute, like:

return 0 2>&1  # redirect on control flow

When this option is disabled, that statement is a syntax error.

parse_triple_quote

Parse the shell-style multi-line strings, which strip leading whitespace:

echo '''    
  one
  two
  '''

echo """
  hello
  $name
  """

(This option affects only command mode. Such strings are always parsed in expression mode.)

parse_ysh_string

Allow r'\' and u'\\' and b'\\' strings, as well as their multi-line versions.

Since shell strings are already raw, this means that YSH just ignores the r prefix:

echo r'\'  # a single backslash

J8 unicode strings:

echo u'mu \u{3bc}'  # mu char

J8 byte strings:

echo b'byte \yff'

(This option affects only command mode. Such strings are always parsed in expression mode.)

sigpipe_status_ok

If a process that's part of a pipeline exits with status 141 when this is option is on, it's turned into status 0, which avoids failure.

SIGPIPE errors occur in cases like 'yes | head', and generally aren't useful.

Generated on Tue, 25 Nov 2025 19:42:44 +0000