Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Built-in utilities

Built-in utilities (or built-ins) are utilities built into the shell, not separate executables. They run directly in the shell process, making them faster and more efficient for certain tasks.

Types of built-in utilities

Yash provides several types of built-in utilities.

Special built-ins

Special built-ins have special meaning or behavior in the shell. They are used for control flow, variable manipulation, and other core tasks. Notable properties:

  • Command search always finds special built-ins first, regardless of PATH.
  • Functions cannot override special built-ins.
  • Assignments in a simple command running a special built-in persist after the command.
  • Errors in special built-ins cause the shell to exit if non-interactive. (See Shell errors)

POSIX.1-2024 defines these special built-ins:

As an extension, yash-rs also supports source as an alias for . (dot). (Since 3.3.4) When the portable option is set, invoking the built-in under the name source is rejected the same way as an elective or extension built-in below; only . may be used.

Mandatory built-ins

Mandatory built-ins must be implemented by all POSIX-compliant shells. They provide essential scripting and command features.

Like special built-ins, they are found regardless of PATH in command search, but they can be overridden by functions.

POSIX.1-2024 defines these mandatory built-ins:

Elective built-ins

Elective built-ins work like mandatory built-ins but are not required by POSIX.1-2024. They provide extra features for scripting or interactive use.

Elective built-ins can be overridden by functions and are found in command search regardless of PATH.

(Since 3.3.4) When the portable option is set, attempting to execute an elective built-in is rejected with an error, even though it is still found in command search.

In yash-rs, the following elective built-in is implemented:

More may be added in the future.

Extension built-ins

Extension built-ins are non-conforming extensions to the POSIX shell that are not permitted by POSIX Command Search and Execution.

Like elective built-ins, they can be found in command search without a corresponding executable in PATH, and they can be overridden by functions.

When the posixlycorrect option is set, extension built-ins are ignored: they are treated as non-existing during command search, so the shell falls through to searching for an external utility with the same name.

When the portable option is set, attempting to execute an extension built-in is rejected with an error, even though it is still found in command search.

No extension built-ins are implemented in yash-rs yet.

Substitutive built-ins

Substitutive built-ins replace external utilities to avoid process creation overhead for common tasks.

Substitutive built-ins behave like external utilities: they are located during command search and can be overridden by functions. However, the built-in is only available if the corresponding external utility exists in PATH. If the external utility is missing from PATH, the built-in is also unavailable, ensuring consistent behavior with the absence of the utility.

Yash-rs implements these substitutive built-ins:

More may be added in the future.

Compatibility

POSIX.1-2024 reserves many names for shell-specific built-ins. Yash-rs implements some of these, and may add more in the future. Other shells may implement these differently:

  • alloc
  • autoload
  • bind
  • bindkey
  • builtin
  • bye
  • caller
  • cap
  • chdir
  • clone
  • comparguments
  • compcall
  • compctl
  • compdescribe
  • compfiles
  • compgen
  • compgroups
  • complete
  • compound
  • compquote
  • comptags
  • comptry
  • compvalues
  • declare
  • dirs
  • disable
  • disown
  • dosh
  • echotc
  • echoti
  • enum
  • float
  • help
  • hist
  • history
  • integer
  • let
  • local
  • login
  • logout
  • map
  • mapfile
  • nameref
  • popd
  • print
  • pushd
  • readarray
  • repeat
  • savehistory
  • shopt
  • source
  • stop
  • suspend
  • typeset
  • whence

Command line argument syntax conventions

Arguments are string parameters passed to built-in utilities. The syntax varies between built-ins, but most follow common conventions. The description below applies to yash-rs built-ins unless otherwise noted.

Operands

Operands are main arguments specifying objects or values for the built-in. For example, in cd, the operand is the directory:

$ cd /dev

Options

Options are supplementary arguments that modify the behavior of the built-in. They start with a hyphen (-) followed by one or more characters. Short options are named with a single character (e.g., -P), while long options are more descriptive and start with two hyphens (e.g., --physical). For example, the cd built-in uses -P or --physical to force the shell to use the physical directory structure instead of preserving symbolic links:

$ cd -P /dev

With a long option:

$ cd --physical /dev

Multiple short options can be combined. For example, cd -P -e /dev can be written as:

$ cd -Pe /dev

Long options must be specified separately.

Long option names can be abbreviated if unambiguous. For example, --p is enough for --physical in cd:

$ cd --p /dev

However, future additions may make abbreviations ambiguous, so use the full name in scripts.

Option arguments

Some options require an argument. For short options, the argument can follow immediately or as a separate argument. For example, -d in read takes a delimiter argument:

$ mkdir $$ && cd $$ || exit
$ echo 12 42 + foo bar > line.txt
$ read -d + a b < line.txt
$ echo "A: $a, B: $b"
A: 12, B: 42

If the argument is non-empty, it can be attached: -d+. If empty, specify separately: -d '':

$ mkdir $$ && cd $$ || exit
$ echo 12 42 + foo bar > line.txt
$ read -d+ a b < line.txt
$ echo "A: $a, B: $b"
A: 12, B: 42
$ read -d '' a b < line.txt
$ echo "A: $a, B: $b"
A: 12, B: 42 + foo bar

For long options, use = or a separate argument:

$ mkdir $$ && cd $$ || exit
$ echo 12 42 + foo bar > line.txt
$ read --delimiter=+ a b < line.txt
$ echo "A: $a, B: $b"
A: 12, B: 42
$ read --delimiter + a b < line.txt
$ echo "A: $a, B: $b"
A: 12, B: 42

Separators

To treat an argument starting with - as an operand, use the -- separator. This tells the shell to stop parsing options. For example, to change to a directory named -P:

$ mkdir $$ $$/-P && cd $$ || exit
$ cd -- -P

Note that a single hyphen (-) is not an option, but an operand. It can be used without --:

$ cd /tmp
$ cd /
$ cd -
/tmp

Argument order

Operands must come after options. All arguments after the first operand are treated as operands, even if they start with a hyphen:

$ cd /dev -P
error: unexpected operand
 --> <stdin>:1:9
  |
1 | cd /dev -P
  | --      ^^ -P: unexpected operand
  | |
  | while executing the cd built-in

Specifying options after operands may be supported in the future.

Compatibility

POSIX.1-2024 only specifies short option syntax. Long options are a yash-rs extension.

(Since 3.3.5) When the portable option is set, non-portable syntax is rejected. Specifically:

  • Long option names are unavailable. Use the corresponding short option instead.
  • An option argument must be separate from its short option name. For example, use read -d :, not read -d:.