source | all docs for version 0.8.pre10 | all versions | oilshell.org
Warning: Work in progress! Leave feedback on Zulip or Github if you'd like this doc to be updated.
This doc describes every aspect of Oil and OSH briefly, and is indexed by keywords.
The help
builtin prints portions of it.
You can also navigate this doc with the help index.
This section describes how to use the Oil binary.
bin/osh
UsageUsage: osh [OPTION]... SCRIPT [ARG]...
osh [OPTION]... -c COMMAND [ARG]...
The command line accepted by bin/osh
is compatible with /bin/sh
and bash
.
osh -c 'echo hi'
osh myscript.sh
echo 'echo hi' | osh
It also has a few enhancements:
osh -n -c 'hello' # pretty-print the AST
osh --ast-format text -n -c 'hello' # print it full
osh accepts POSIX sh flags, with these additions:
-n parse the program but don't execute it. Print the AST. --ast-format what format the AST should be in
bin/oil
UsageUsage: oil [OPTION]... SCRIPT [ARG]...
oil [OPTION]... -c COMMAND [ARG]...
bin/oil
is the same as bin/osh
with a the oil:all
option group set. So
bin/oil
also accepts shell flags.
oil -c 'echo hi'
oil myscript.oil
echo 'echo hi' | oil
Usage: oil.ovm MAIN_NAME [ARG]...
MAIN_NAME [ARG]...
oil.ovm behaves like busybox. If it's invoked through a symlink, e.g. 'osh', then it behaves like that binary. Otherwise the binary name can be passed as the first argument, e.g.:
oil.ovm osh -c 'echo hi'
If the --rcfile flag is specified, that file will be executed on startup. Otherwise:
bin/osh
runs ~/.config/oil/oshrc
bin/oil
runs ~/.config/oil/oilrc
Pass --rcfile /dev/null to disable this behavior.
History is read?
A comment starts with #
and goes until the end of the line.
echo hi # print a greeting
A backslash \
at the end of a line continues the line without executing it:
ls /usr/bin \
/usr/lib \
~/src # A single command split over three lines
The %%% prefix Starts a Single Command Over Multiple Lines (?)
This special lexer mode has several use cases:
Long command lines without trailing \
%%% chromium-browser
--no-proxy-server
# comments allowed
--incognito
Long pipelines or and-or chains without trailing \
%%% find .
# exclude tests
| grep -v '_test.py'
| xargs wc -l
| sort -n
%%% ls /
&& ls /bin
&& ls /lib
|| error "oops"
TODO
Commands are composed of words. The first word may by the name of a shell builtin, an Oil proc / shell "function", an external command, or an alias:
echo hi # a shell builtin doesn't start a process
ls /usr/bin ~/src # starts a new process
myproc "hello $name"
myshellfunc "hello $name"
myalias -l
Redirects are also allowed in any part of the command:
echo 'to stderr' >&2
echo >&2 'to stderr'
echo 'to file' > out.txt
echo > out.txt 'to file'
Run two commands in sequence like this:
echo one; echo two
or this:
echo one
echo two
Match a string against a series of glob patterns. Execute code in the section below the matching pattern.
path='foo.py'
case "$path" in
*.py)
echo 'python'
;;
*.sh)
echo 'shell'
;;
esac
Test if a command exited with status zero (true). If so, execute the corresponding block of code.
Shell:
if test -d foo; then
echo 'foo is a directory'
elif test -f foo; then
echo 'foo is a file'
else
echo 'neither'
fi
Oil:
if test -d foo {
echo 'foo is a directory'
} elif test -f foo {
echo 'foo is a file'
} else {
echo 'neither'
}
Do nothing and return status 0.
if true; then
echo hello
fi
Do nothing and return status 1.
if false; then
echo 'not reached'
else
echo hello
fi
For loops iterate over words.
Oil style:
var mystr = 'one'
var myarray = @(two three)
for i in $mystr @myarray *.py; done
echo $i
done
Shell style:
mystr='one'
myarray=(two three)
for i in "mystr" "${myarray[@]}" *.py; done
echo $i
done
Both fragments output 3 lines and then Python files on remaining lines.
Three variants of redirecting stdout:
echo foo > out.txt # write to a file
echo foo >> out.txt # append to a file
echo foo >| out.txt # clobber the file even if set -o noclobber
Redirect stdin:
cat < in.txt
Redirect to a file descriptor:
echo 'to stderr' >&2
TODO: unbalanced HTML if we use <<?
cat <<EOF
here doc with $double ${quoted} substitution
EOF
myfunc() {
cat <<-EOF
here doc with one tab leading tab stripped
EOF
}
cat <<< 'here string'
time [-p] pipeline
Measures the time taken by a command / pipeline. It uses the getrusage()
function from libc
.
Note that time is a KEYWORD, not a builtin!
Initializes a constant name to the Oil expression on the right.
const c = 'mystr' # equivalent to readonly c=mystr
const pat = / digit+ / # an eggex, with no shell equivalent
It's either a global constant or scoped to the current function.
Initializes a name to the Oil expression on the right.
var s = 'mystr' # equivalent to declare s=mystr
var pat = / digit+ / # an eggex, with no shell equivalent
It's either a global or scoped to the current function.
Like shell's x=1
, setvar x = 1
either:
var
)It's meant for interactive use and to easily convert existing shell scripts.
New Oil programs should use set
, setglobal
, or setref
instead of
setvar
.
A shorter name for setlocal
in the Oil language. Requires shopt -s parse_set
, because otherwise it would conflict with the set
builtin. Use
builtin set -- 1 2 3
to get the builtin, or shopt -o
to change options.
Mutates an existing variable in the current scope. If it doesn't exist, the shell exits with a fatal error.
Mutates a global variable. If it doesn't exist, the shell exits with a fatal error.
Mutates a variable through a named reference. TODO: Show example.
Array literals in shell accept any sequence of words, just like a command does:
ls $mystr "$@" *.py
# Put it in an array
a=(ls $mystr "$@" *.py)
In Oil, use oil-array.
Oil strings appear in expression contexts, and look like shell strings:
var s = 'foo'
var double = "hello $world and $(hostname)"
However, strings with backslashes are forced to specify whether they're raw strings or C-style strings:
var s = 'line\n' # parse error: ambiguous
var s = c'line\n' # C-style string
var s = $'line\n' # also accepted for compatibility
var s = r'[a-z]\n' # raw strings are useful for regexes (not eggexes)
Like shell arays, Oil arrays accept anything that can appear in a command:
ls $mystr @ARGV *.py
# Put it in an array
var a = @(ls $mystr @ARGV *.py)
$'\n'
Also see oil-string.
Evaluates to the stdout of a command. If a trailing newline is returned, it's stripped:
$ hostname
example.com
$ x=$(hostname)
$ echo $x
example.com
Evaluates to the value of a variable:
$ x=X
$ echo $x ${x}
X X
Shell has C-style arithmetic:
$ echo $(( 1 + 2*3 ))
7
Used as a shortcut for a user's home directory:
~/src # my home dir
~bob/src # user bob's home dir
${x@P} evaluates x as a prompt string, e.g. the string that would be printed if PS1=$x.
These builtins take input and output. They're often used with redirects.
read FLAG* VAR*
Read a line from stdin, split it into tokens with the $IFS
algorithm,
and assign the tokens to the given variables. When no VARs are given,
assign to $REPLY
.
Flags:
-a ARRAY assign the tokens to elements of this array
-d CHAR use DELIM as delimiter, instead of newline
-n NUM read up to NUM characters, respecting delimiters
-p STR print the string PROMPT before reading input
-r raw mode: don't let backslashes escape characters
-s silent: do not echo input coming from a terminal
-t NUM time out and fail after TIME seconds
-t 0 returns whether any input is available
-u FD read from file descriptor FD instead of 0 (stdin)
echo FLAG* ARG*
Prints ARGs to stdout, separated by a space, and terminated by a newline.
Flags:
-e enable interpretation of backslash escapes
-n omit the trailing newline
Backslash sequences recognized by -e:
\\ backslash
\a (unimplemented ?) alert (BEL)
\b backspace
\c stop processing remaining input
\e escape next character
\f form feed, equivalent to \n + 4 spaces
\n new line
\r carriage return, returns to the beggining of the line
\t horizontal tab
\v vertical tab
\0NNN print character specified as an octal value with 1 to 3 octal
digits
\xHH print character specified as an hexadecimal value with 1 to 2
hex digits
\uHHHH Unicode character specified as an hexadecimal value with 1 to
4 hex digits
\UHHHHHHHH Unicode character specified as an hexadecimal value with 1 to
8 hex digits
Alias for mapfile
.
mapfile FLAG* ARRAY?
Reads lines from stdin into the variable named ARRAY (default
${MAPFILE[@]}
).
Flags:
-t Remove the trailing newline from every line
source SCRIPT ARG*
Executes SCRIPT with given ARGs in the context of the current shell. It will modify existing variables.
eval ARG+
Creates a string by joining ARGs with a space, then runs it as a shell command.
Example:
# Create the string echo "hello $name" and run it.
a='echo'
b='"hello $name"'
eval $a $b
Tips:
eval
is usually unnecessary in Oil code. Using it can confuse code and
user-supplied data, leading to security issues.
Prefer passing single string ARG to eval
.
trap FLAG* CMD SIGNAL*
Registers the shell string CMD to be run after the SIGNALs are received. If the CMD is empty, then the signal is ignored.
Flags:
-l Lists all signals and their signal number
-p Prints a list of the installed signal handlers
Tip:
Prefer passing the name of a shell function to trap
.
The set builtin modifies the shell's configuration and behavior.
The shopt builtin configures the shell.
cd FLAG* DIR
Changes the working directory of the current shell process to DIR.
If DIR isn't specified, change to $HOME
. If DIR is -
, change to $OLDPWD
(a variable that the sets to the previous working directory.)
Flags:
-L Follow symbolic links, i.e. change to the TARGET of the symlink.
(default).
-P Don't follow symbolic links.
pwd FLAG*
Prints the current working directory.
Flags:
-L Follow symbolic links if present (default)
-P Don't follow symbolic links. Print the link instead of the target.
pushd DIR
Add DIR to the directory stack, then change the working directory to DIR.
Typically used with popd
and dirs
.
popd
Removes a directory from the directory stack, and changes the working directory
to it. Typically used with pushd
and dirs
.
dirs FLAG*
Shows the contents of the directory stack. Typically used with pushd
and
popd
.
Flags:
-c Clear the dir stack.
-l Show the dir stack, but with the real path instead of ~.
-p Show the dir stack, but formatted as one line per entry.
-v Like -p, but numbering each line.
The complete builtin registers completion policies for different commands.
The compgen builtin generates completion candidates inside a user-defined completion function.
It can also be used in scripts, i.e. outside a completion function.
The compopt builtin changes completion options inside a user-defined completion function.
The compadjust builtin adjusts COMP_ARGV according to specified delimiters, and optionally set variables cur, prev, words (an array), and cword. May also set 'split'.
This is an OSH extension that makes it easier to run the bash-completion project.
exec BIN_PATH ARG*
Replaces the running shell with the binary specified, which is passed ARGs. BIN_PATH must exist on the file system; i.e. it can't be a shell builtin or function.
umask MODE?
Sets the bit mask that determines the permissions for new files and directories. The mask is subtracted from 666 for files and 777 for directories.
Oil currently supports writing masks in octal.
If no MODE, show the current mask.
times
Shows the user and system time used by the shell and its child processes.
jobs
Shows all jobs running in the shell and their status.
wait FLAG* ARG
Waits for a a process to exit, and returns its status.
The ARG can be a PID (tracked by the kernel), or a job number (tracked by the
shell). Specify jobs with the syntax %jobnumber
.
If there's no ARG, wait for all child processes.
Flags:
-n Wait for the next process to exit, rather than a specific process.
CMD &
The &
language construct runs CMD in the background as a job, immediately
returning control to the shell.
The resulting PID is recorded in the $!
variable.
fg JOB?
Returns a job running in the background to the foreground. If no JOB is specified, use the latest job.
TODO
Bash has this, but OSH won't implement it.
help index # list all help topics
help index GROUP... # list help topics in the given groups
help TOPIC # show help on a given topic
help osh-usage # same as osh --help
help oil-usage # same as oil --help
View on the web: http://www.oilshell.org/$VERSION/doc/osh-quick-ref.html
Displays the internal representation of a cell. (Cells are locations for values like strings and arrays.)
Normally, when no files match a glob, the glob itself is returned:
$ echo L *.py R # no Python files in this dir
L *.py R
With nullglob on, the glob expands to no arguments:
shopt -s nullglob
$ echo L *.py R
L R
(This option is in GNU bash as well.)
Do globs return results that start with -
? It's on by default in bin/osh
,
but off when Oil 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
Failed tilde expansions cause hard errors (like zsh) rather than silently
evaluating to ~
or ~bad
.
TODO
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
For compatibility, Oil 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.
TODO:
For the 'set' builtin.
For the 'shopt' builtin.
$HOME is used for:
Note: The shell doesn't set $HOME. According to POSIX, the program that invokes the login shell sets it based on /etc/passwd.
A colon-separated string that's used to find executables to run.
Used for word splitting. And the builtin split() function.
An array of words, split by : and = for compatibility with bash. New completion scripts should use COMP_ARGV instead.
Discouraged; for compatibility with bash.
Discouraged; for compatibility with bash.
Discouraged; for compatibility with bash.
User-defined completion functions should Fill this array with candidates. It is cleared on every completion request.
An array of partial command arguments to complete. Preferred over COMP_WORDS. The compadjust builtin uses this variable.
(An OSH extension to bash.)
First line of a prompt.
Second line of a prompt.
For the 'select' builtin (unimplemented).
For 'set -o xtrace'. The leading character is special.
len()
len(mystr)
is its length in byteslen(myarray)
is the number of elementslen(assocarray)
is the number of pairscopy()
:
var d = {name: value}
var alias = d # illegal, because it can create ownership problems
# reference cycles
var new = copy(d) # valid
regmatch(/d+/, s)
returns a match objectfnmatch('*.py', s)
returns a booleanThese functions give better syntax to existing shell constructs.
shquote()
for printf %q
and ${x@Q}
lstrip()
for ${x#prefix}
and ${x##prefix}
rstrip()
for ${x%suffix}
and ${x%%suffix}
lstripglob()
and rstripglob()
for slow, legacy globupper()
for ${x^^}
lower()
for ${x,,}
strftime()
: hidden in printf
index(A, item)
is like the awk function@names()
values()
. Problem: these aren't all strings?Useful for logging callbacks. NOTE: bash has this with the obscure printf '%(...)' syntax.
TODO