I don't understand why they are both needed since they seem that zstyle does the same as setopt and even more?

  • Could you say something more about why you think these two commands do the same thing in the zsh shell? I find it bit difficult to see this.
    – Kusalananda
    Jun 19, 2022 at 13:00
  • From what I understand setopt sets options for the zsh shell, zstyle sets options for how a module would behave. But also my view of zsh was that the modules are mostly responsible for functionalities so most options could be set via zstyle without setopt.
    – aja228
    Jun 19, 2022 at 13:11

2 Answers 2


setopt sets shell options

Shell options are a boolean variables that change the behavior of the shell itself. setopt toggles them on or off. Run setopt without arguments to see which shell options have been toggled from their default value. Some of these are not possible to change at runtime; instead, they are to provide info about the shell’s internal state.

What shell options are available is determined by the shell; it’s not possible to create your own. However, any piece of shell code can decide to read the value of a shell option and change its own behavior accordingly. Additionally, a shell function or executable shell script (but not one that is sourced) can change shell options locally, without affecting the rest of the shell around it.

zstyle provides namespaced properties

zstyle [<flag>] ( <namespace> | <selector> ) <property> <value> is Zsh’s alternative to global variables. It allows shell code to provide a way for users to configure settings, as well as store its own internal state, without polluting your shell with actual global variables.

Unlike a shell option, a zstyle property cannot be made local. Instead, zstyle uses a system of namespaces and selectors. When reading a zstyle property, you pass a namespace and the name of the property from which you want to read. However, when setting a zstyle property, you pass a glob pattern that functions similar to a CSS selector, letting you set the same property for multiple namespaces at once. (This similarity to CSS appears to be the reason for the use of the word "style" here.)

Note that zstyle does not care what syntax you use for your namespaces. Using : as a hierarchical separator (as is done in Zsh’s completion system) is merely a convention.

Each zstyle property stores an array of strings. However:

  • If you pass the -e flag when setting a property, the strings are evaluated as code when the property is read, enabling the creation of computed properties – something which is not possible with global variables.
  • zstyle offers several convenience methods for getting and testing values, to let you more easily convert these string arrays to other types.

Looking at history helps.

zsh was first released in 1990. It took the best from both the Bourne shell and csh.

The Bourne shell tuning was done with single-letter options to sh, which could also be tweaked with the set special built-in. For instance, sh -f starts sh with globbing disabled, or set -f disables globbing at runtime.

csh was tuned with plain variables which you'd set or unset, some of which were mapped to start-up options. For instance, csh -x starts csh in a mode where it prints everything it's doing. Or you can do set verbose to enter that mode at runtime (unset verbose to leave it).

A lot of zsh was based on csh as csh was the popular shell at the time. Here, it mimicked csh, but recognising that using plain variables to store option settings was a bad idea, it did use a different namespace for options and separate builtins to set/unset them: setopt and unsetopt, and those options were mapped to single-letter options.

ksh in the 80s gave names to some of the Bourne options so you could set them alternatively with set -o optionName (unset with set +o).

In zsh 2.0.02 in 1991, setopt / unsetopt were aliased to set -o / set +o for compatibility with ksh.

For comparison, bash at the time had options as plain variables like in csh, some mapped to start-up / set options, while some of the start-up / set options were not all mapped to corresponding variables.

set -o option was added to bash at some point between 1.06 and 1.08 circa 1990.

In bash 2.0 (1996), those variables were removed and shopt introduced as replacement so you had two sets of options, some set with set -o / set +o some with shopt -s / shopt -u. It's not clear to me why.

AFAIK, set -o was already in the POSIX.2 specification for sh when it was first released in 1992. And is supported by all modern Bourne-like shells to set options, though the list of options varies from shell to shell outside of the ones specified by POSIX (and see bash's second set of option as mentioned above), so I tend to use set -o instead of setopt myself.

zstyle itself was added much later in 1999 in an optional module as a generalisation and reimplementation in C of an earlier compstyle approach written as a zsh function. Its primary use case was and still is to allow fine tuning of the new completion system (though it can be and has been used since for other things)

It's a separate namespace from shell options or variables or functions. While shell options or variables can be made local to a function, zstyles AFAIK are always global, so if only for that, options or variables could not be reimplemented using zstyles, not that there would be much value in that. The set -o / setopt would still have to be kept around anyway for backward compatibility.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .