OILS / doc / ref / chap-builtin-cmd.md View on Github | oilshell.org

1491 lines, 959 significant
1---
2title: Builtin Commands (Oils Reference)
3all_docs_url: ..
4body_css_class: width40
5default_highlighter: oils-sh
6preserve_anchor_case: yes
7---
8
9<div class="doc-ref-header">
10
11[Oils Reference](index.html) &mdash; Chapter **Builtin Commands**
12
13</div>
14
15This chapter in the [Oils Reference](index.html) describes builtin commands for OSH and YSH.
16
17<span class="in-progress">(in progress)</span>
18
19<div id="dense-toc">
20</div>
21
22## Memory
23
24### cmd/append
25
26Append word arguments to a list:
27
28 var mylist = :| hello |
29
30 append *.py (mylist) # append all Python files
31
32 var myflags = []
33 append -- -c 'echo hi' (myflags) # -- to avoid ambiguity
34
35It's a shortcut for:
36
37 call myflags->append('-c')
38 call myflags->append('echo hi')
39
40Similar names: [append][]
41
42[append]: chap-index.html#append
43
44### pp
45
46Pretty prints interpreter state. Some of these are implementation details,
47subject to change.
48
49Examples:
50
51 pp proc # print all procs and their doc comments
52
53 var x = :| one two |
54 pp cell x # dump the "guts" of a cell, which is a location for a value
55
56 pp asdl (x) # dump the ASDL "guts"
57
58 pp line (x) # single-line stable format, for spec tests
59
60## Handle Errors
61
62### error
63
64The `error` builtin interrupts shell execution.
65
66If there's a surrounding `try` block, the `_error` register is set, and
67execution proceeds after the block.
68
69Otherwise, the shell exits with a non-zero status.
70
71Examples:
72
73 error 'Missing /tmp' # program fails with status 10
74
75 try {
76 error 'Another problem'
77 }
78 echo $[error.code] # => 10
79
80Override the default error code of `10` with a named argument:
81
82 error 'Missing /tmp' (code=99) # program fails with status 99
83
84Named arguments add arbitrary properties to the resulting `_error` register:
85
86 error 'Oops' (path='foo.json')
87
88See [YSH Error Handling](../ysh-error-handling.html) for more examples.
89
90### failed
91
92A shortcut for `(_error.code !== 0)`:
93
94 try {
95 ls /tmp
96 }
97 if failed {
98 echo 'ls failed'
99 }
100
101It saves you 7 punctuation characters: `( _ . !== )`
102
103See [YSH Error Handling](../ysh-error-handling.html) for more examples.
104
105### try
106
107Run a block of code, stopping at the first error. (This is implemented with
108`shopt --set errexit`)
109
110`try` sets the `_error` register to a dict, and always returns 0.
111
112 try {
113 ls /nonexistent
114 }
115 if (_error.code !== 0) {
116 echo 'ls failed'
117 }
118
119Handle expression errors:
120
121 try {
122 var x = 42 / 0
123 }
124
125And errors from compound commands:
126
127 try {
128 ls | wc -l
129 diff <(sort left.txt) <(sort right.txt)
130 }
131
132The case statement can be useful:
133
134 try {
135 grep PATTERN FILE.txt
136 }
137 case (_error.code) {
138 (0) { echo 'found' }
139 (1) { echo 'not found' }
140 (else) { echo "grep returned status $[_error.code]" }
141 }
142
143See [YSH Error Handling](../ysh-error-handling.html) for more examples.
144
145### boolstatus
146
147Runs a command, and requires the exit code to be 0 or 1.
148
149 if boolstatus egrep '[0-9]+' myfile { # e.g. aborts on status 2
150 echo 'found' # status 0 means found
151 } else {
152 echo 'not found' # status 1 means not found
153 }
154
155It's meant for external commands that "return" more than 2 values, like true /
156false / fail, rather than pass / fail.
157
158## Shell State
159
160### ysh-cd
161
162It takes a block:
163
164 cd / {
165 echo $PWD
166 }
167
168### ysh-shopt
169
170It takes a block:
171
172 shopt --unset errexit {
173 false
174 echo 'ok'
175 }
176
177### shvar
178
179Execute a block with a global variable set.
180
181 shvar IFS=/ {
182 echo "ifs is $IFS"
183 }
184 echo "ifs restored to $IFS"
185
186### ctx
187
188Execute a block with a shared "context" that can be updated using the `ctx`
189built-in.
190
191 var mydict = {}
192 ctx push (mydict) {
193 # = mydict => {}
194 ctx set (mykey='myval')
195 }
196 # = mydict => { mykey: 'myval' }
197
198The context can be modified with `ctx set (key=val)`, which updates or inserts
199the value at the given key.
200
201The context can also be updated with `ctx emit field (value)`.
202
203 ctx push (mydict) {
204 # = mydict => {}
205 ctx emit mylist (0)
206 # = mydict => { mylist: [0] }
207 ctx emit mylist (1)
208 }
209 # = mydict => { mylist: [0, 1] }
210
211Contexts can be nested, resulting in a stack of contexts.
212
213 ctx push (mydict1) {
214 ctx set (dict=1)
215 ctx push (mydict2) {
216 ctx set (dict=2)
217 }
218 }
219 # = mydict1 => { dict: 1 }
220 # = mydict2 => { dict: 2 }
221
222`ctx` is useful for creating DSLs, such as a mini-parseArgs.
223
224 proc parser (; place ; ; block_def) {
225 var p = {}
226 ctx push (p, block_def)
227 call place->setValue(p)
228 }
229
230 proc flag (short_name, long_name; type; help) {
231 ctx emit flag ({short_name, long_name, type, help})
232 }
233
234 proc arg (name) {
235 ctx emit arg ({name})
236 }
237
238 parser (&spec) {
239 flag -t --tsv (Bool, help='Output as TSV')
240 flag -r --recursive (Bool, help='Recurse into the given directory')
241 flag -N --count (Int, help='Process no more than N files')
242 arg path
243 }
244
245### push-registers
246
247Save global registers like $? on a stack. It's useful for preventing plugins
248from interfering with user code. Example:
249
250 status_42 # returns 42 and sets $?
251 push-registers { # push a new frame
252 status_43 # top of stack changed here
253 echo done
254 } # stack popped
255 echo $? # 42, read from new top-of-stack
256
257Current list of registers:
258
259 Regex data underlying BASH_REMATCH, _group(), _start(), _end()
260 $?
261 _error # set by the try builtin
262 PIPESTATUS # aka _pipeline_status
263 _process_sub_status
264
265
266## Modules
267
268### runproc
269
270Runs a named proc with the given arguments. It's often useful as the only top
271level statement in a "task file":
272
273 proc p {
274 echo hi
275 }
276 runproc @ARGV
277
278Like 'builtin' and 'command', it affects the lookup of the first word.
279
280### module
281
282Registers a name in the global module dict. Returns 0 if it doesn't exist, or
2831 if it does.
284
285Use it like this in executable files:
286
287 module main || return 0
288
289And like this in libraries:
290
291 module myfile.ysh || return 0
292
293### is-main
294
295The `is-main` builtin returns 1 (false) if the current file was executed with
296the `source` builtin.
297
298In the "main" file, including `-c` or `stdin` input, it returns 0 (true).
299
300Use it like this:
301
302 if is-main {
303 runproc @ARGV
304 }
305
306### use
307
308TODO
309
310Reuse code from other files, respecting namespaces.
311
312 use lib/foo.ysh # relative import, i.ie implicit $_this_dir?
313 # makes name 'foo' available
314
315Bind a specific name:
316
317 use lib/foo.ysh (&myvar) # makes 'myvar' available
318
319Bind multiple names:
320
321 use lib/foo.ysh (&myvar) {
322 var log, die
323 }
324
325Maybe:
326
327 use lib/foo.ysh (&myvar) {
328 var mylog = myvar.log
329 }
330
331Also a declaration
332
333 use --extern grep sed
334
335## I/O
336
337### ysh-read
338
339YSH adds long flags to shell's `read`:
340
341 read --all # whole file including trailing \n, fills $_reply
342 read --all (&x) # fills $x
343
344 read --num-bytes 3 # read N bytes, fills _reply
345 read --num-bytes 3 (&x) # fills $x
346
347 read --raw-line # unbuffered read of line, omitting trailing \n
348 read --raw-line (&x) # fills $x
349
350 read --raw-line --with-eol # include the trailing \n
351
352And a convenience:
353
354 read -0 # read until NUL, synonym for read -r -d ''
355
356You may want to use `fromJson8()` or `fromJson()` after reading a line.
357
358<!--
359
360TODO:
361
362- read --netstr
363- fromJ8Line() is different than from Json8! It's like @()
364
365-->
366
367<!--
368
369Problem with read --json -- there's also https://jsonlines.org, which allows
370
371 {"my": "line"}
372
373That can be done with
374
375 while read --line {
376 var record = fromJson(_reply)
377 }
378
379This is distinct from:
380
381 while read --line --j8 {
382 echo $_reply
383 }
384
385This allows unquoted. Maybe it should be read --j8-line
386
387What about write? These would be the same:
388
389 write --json -- $s
390 write --j8 -- $s
391
392 write -- $[toJson(s)]
393 write -- $[toJson8(s)]
394
395 write --json -- @strs
396 write --j8 -- @strs
397
398 write -- @[toJson(s) for s in strs]
399 write -- @[toJson8(s) for s in strs]
400
401It's an argument for getting rid --json and --j8? I already implemented them,
402but it makes the API smaller.
403
404I guess the main thing would be to AVOID quoting sometimes?
405
406 $ write --j8 -- unquoted
407 unquoted
408
409 $ write --j8 -- $'\'' '"'
410 "'"
411 "\""
412
413I think this could be the shell style?
414
415 $ write --shell-str -- foo bar baz
416
417Or it could be
418
419 $ write -- @[toShellString(s) for s in strs]
420
421I want this to be "J8 Lines", but it can be done in pure YSH. It's not built
422into the interpreter.
423
424 foo/bar
425 "hi"
426b'hi'
427u'hi'
428
429But what about
430
431 Fool's Gold
432a'hi' # This feels like an error?
433a"hi" # what about this?
434
435Technically we CAN read those as literal strings
436-->
437
438### ysh-echo
439
440Print arguments to stdout, separated by a space.
441
442 ysh$ echo hi there
443 hi there
444
445The [simple_echo][] option means that flags aren't accepted, and `--` is not
446accepted.
447
448 ysh$ echo -n
449 -n
450
451See the [YSH FAQ][echo-en] for details.
452
453[simple_echo]: chap-option.html#ysh:all
454[echo-en]: ../ysh-faq.html#how-do-i-write-the-equivalent-of-echo-e-or-echo-n
455
456### write
457
458write fixes problems with shell's `echo` builtin.
459
460The default separator is a newline, and the default terminator is a
461newline.
462
463Examples:
464
465 write -- ale bean # write two lines
466
467 write -n -- ale bean # synonym for --end '', like echo -n
468 write --sep '' --end '' -- a b # write 2 bytes
469 write --sep $'\t' --end $'\n' -- a b # TSV line
470
471You may want to use `toJson8()` or `toJson()` before writing:
472
473 write -- $[toJson8(mystr)]
474 write -- $[toJson(mystr)]
475
476
477<!--
478 write --json -- ale bean # JSON encode, guarantees two lines
479 write --j8 -- ale bean # J8 encode, guarantees two lines
480-->
481
482
483### fork
484
485Run a command, but don't wait for it to finish.
486
487 fork { sleep 1 }
488 wait -n
489
490In YSH, use `fork` rather than shell's `&` ([ampersand][]).
491
492[ampersand]: chap-cmd-lang.html#ampersand
493
494### forkwait
495
496The preferred alternative to shell's `()`. Prefer `cd` with a block if possible.
497
498 forkwait {
499 not_mutated=zzz
500 }
501 echo $not_mutated
502
503### fopen
504
505Runs a block passed to it. It's designed so redirects have a **prefix**
506syntax:
507
508 fopen >out.txt {
509 echo 1
510 echo 2
511 }
512
513Rather than shell style:
514
515 { echo 1
516 echo 2
517 } >out.txt
518
519When a block is long, the former is more readable.
520
521## Hay Config
522
523### hay
524
525### haynode
526
527
528## Data Formats
529
530### json
531
532Write JSON:
533
534 var d = {name: 'bob', age: 42}
535 json write (d) # default indentation of 2
536 json write (d, space=0) # no indentation
537
538Read JSON:
539
540 echo hi | json read # fills $_reply by default
541
542Or use an explicit place:
543
544 var x = ''
545 json read (&x) < myfile.txt
546
547Related: [err-json-encode][] and [err-json-decode][]
548
549[err-json-encode]: chap-errors.html#err-json-encode
550[err-json-decode]: chap-errors.html#err-json-decode
551
552### json8
553
554Like `json`, but on the encoding side:
555
556- Falls back to `b'\yff'` instead of lossy Unicode replacement char
557
558On decoding side:
559
560- Understands `b'' u''` strings
561
562Related: [err-json8-encode]() and [err-json8-decode]()
563
564[err-json8-encode]: chap-errors.html#err-json8-encode
565[err-json8-decode]: chap-errors.html#err-json8-decode
566
567## Testing
568
569TODO: describe
570
571## External Lang
572
573TODO: when
574
575
576## I/O
577
578These builtins take input and output. They're often used with redirects.
579
580### read
581
582 read FLAG* VAR*
583
584Read a line from stdin, split it into tokens with the `$IFS` algorithm,
585and assign the tokens to the given variables. When no VARs are given,
586assign to `$REPLY`.
587
588Note: When writing ySH, prefer the extensions documented in
589[ysh-read](#ysh-read). The `read` builtin is confusing because `-r` needs to
590be explicitly enabled.
591
592Flags:
593
594 -a ARRAY assign the tokens to elements of this array
595 -d CHAR use DELIM as delimiter, instead of newline
596 -n NUM read up to NUM characters, respecting delimiters
597 -p STR print the string PROMPT before reading input
598 -r raw mode: don't let backslashes escape characters
599 -s silent: do not echo input coming from a terminal
600 -t NUM time out and fail after TIME seconds
601 -t 0 returns whether any input is available
602 -u FD read from file descriptor FD instead of 0 (stdin)
603
604 <!-- -N NUM read up to NUM characters, ignoring delimiters -->
605 <!-- -e use readline to obtain the line
606 -i STR use STR as the initial text for readline -->
607
608### echo
609
610 echo FLAG* ARG*
611
612Prints ARGs to stdout, separated by a space, and terminated by a newline.
613
614Flags:
615
616 -e enable interpretation of backslash escapes
617 -n omit the trailing newline
618<!-- -E -->
619
620See [char-escapes](chap-mini-lang.html#char-escapes).
621
622### printf
623
624 printf FLAG* FMT ARG*
625
626Formats values and prints them. The FMT string contain three types of objects:
627
6281. Literal Characters
6292. Character escapes like `\t`. See [char-escapes](chap-mini-lang.html#char-escapes).
6303. Percent codes like `%s` that specify how to format each each ARG.
631
632If not enough ARGS are passed, the empty string is used. If too many are
633passed, the FMT string will be "recycled".
634
635Flags:
636
637 -v VAR Write output in variable VAR instead of standard output.
638
639Format specifiers:
640
641 %% Prints a single "%".
642 %b Interprets backslash escapes while printing.
643 %q Prints the argument escaping the characters needed to make it reusable
644 as shell input.
645 %d Print as signed decimal number.
646 %i Same as %d.
647 %o Print as unsigned octal number.
648 %u Print as unsigned decimal number.
649 %x Print as unsigned hexadecimal number with lower-case hex-digits (a-f).
650 %X Same as %x, but with upper-case hex-digits (A-F).
651 %f Print as floating point number.
652 %e Print as a double number, in "±e" format (lower-case e).
653 %E Same as %e, but with an upper-case E.
654 %g Interprets the argument as double, but prints it like %f or %e.
655 %G Same as %g, but print it like %E.
656 %c Print as a single char, only the first character is printed.
657 %s Print as string
658 %n The number of characters printed so far is stored in the variable named
659 in the argument.
660 %a Interprets the argument as double, and prints it like a C99 hexadecimal
661 floating-point literal.
662 %A Same as %a, but print it like %E.
663 %(FORMAT)T Prints date and time, according to FORMAT as a format string
664 for strftime(3). The argument is the number of seconds since
665 epoch. It can also be -1 (current time, also the default value
666 if there is no argument) or -2 (shell startup time).
667
668### readarray
669
670Alias for `mapfile`.
671
672### mapfile
673
674 mapfile FLAG* ARRAY?
675
676Reads lines from stdin into the variable named ARRAY (default
677`${MAPFILE[@]}`).
678
679Flags:
680
681 -t Remove the trailing newline from every line
682<!--
683 -d CHAR use CHAR as delimiter, instead of the default newline
684 -n NUM copy up to NUM lines
685 -O NUM begins copying lines at the NUM element of the array
686 -s NUM discard the first NUM lines
687 -u FD read from FD file descriptor instead of the standard input
688 -C CMD run CMD every NUM lines specified in -c
689 -c NUM every NUM lines, the CMD command in C will be run
690-->
691
692## Run Code
693
694These builtins accept shell code and run it.
695
696### source
697
698 source SCRIPT ARG*
699
700Executes SCRIPT with given ARGs in the context of the current shell. It will
701modify existing variables.
702
703### eval
704
705 eval ARG+
706
707Creates a string by joining ARGs with a space, then runs it as a shell command.
708
709Example:
710
711 # Create the string echo "hello $name" and run it.
712 a='echo'
713 b='"hello $name"'
714 eval $a $b
715
716Tips:
717
718- Using `eval` can confuse code and user-supplied data, leading to [security
719issues][].
720- Prefer passing single string ARG to `eval`.
721
722[security issues]: https://mywiki.wooledge.org/BashFAQ/048
723
724YSH eval:
725
726 var myblock = ^(echo hi)
727 eval (myblock) # => hi
728
729
730### trap
731
732 trap FLAG* CMD SIGNAL*
733
734Registers the shell string CMD to be run after the SIGNALs are received. If
735the CMD is empty, then the signal is ignored.
736
737Flags:
738
739 -l Lists all signals and their signal number
740 -p Prints a list of the installed signal handlers
741
742Tip:
743
744Prefer passing the name of a shell function to `trap`.
745
746## Set Options
747
748The `set` and `shopt` builtins set global shell options. YSH code should use
749the more natural `shopt`.
750
751### set
752
753 set FLAG* ARG*
754
755Sets global shell options. Short style:
756
757 set -e
758
759Long style:
760
761 set -o errexit
762
763Set the arguments array:
764
765 set -- 1 2 3
766
767### shopt
768
769 shopt FLAG* OPTION* BLOCK?
770
771Sets global shell options.
772
773Flags:
774
775 -s --set Turn the named options on
776 -u --unset Turn the named options off
777 -p Print option values
778 -o Use older set of options, normally controlled by 'set -o'
779 -q Return 0 if the option is true, else 1
780
781Examples:
782
783 shopt --set errexit
784
785You can set or unset multiple options with the groups `strict:all`,
786`ysh:upgrade`, and `ysh:all`.
787
788If a block is passed, then the mutated options are pushed onto a stack, the
789block is executed, and then options are restored to their original state.
790
791## Working Dir
792
793These 5 builtins deal with the working directory of the shell.
794
795### cd
796
797 cd FLAG* DIR
798
799Changes the working directory of the current shell process to DIR.
800
801If DIR isn't specified, change to `$HOME`. If DIR is `-`, change to `$OLDPWD`
802(a variable that the sets to the previous working directory.)
803
804Flags:
805
806 -L Follow symbolic links, i.e. change to the TARGET of the symlink.
807 (default).
808 -P Don't follow symbolic links.
809
810### pwd
811
812 pwd FLAG*
813
814Prints the current working directory.
815
816Flags:
817
818 -L Follow symbolic links if present (default)
819 -P Don't follow symbolic links. Print the link instead of the target.
820
821### pushd
822
823<!--pushd FLAGS DIR-->
824 pushd DIR
825<!--pushd +/-NUM-->
826
827Add DIR to the directory stack, then change the working directory to DIR.
828Typically used with `popd` and `dirs`.
829
830<!--FLAGS:
831 -n Don't change the working directory, just manipulate the stack
832NUM:
833 Rotates the stack the number of places specified. Eg, given the stack
834 '/foo /bar /baz', where '/foo' is the top of the stack, pushd +1 will move
835 it to the bottom, '/bar /baz /foo'-->
836
837### popd
838
839 popd
840
841Removes a directory from the directory stack, and changes the working directory
842to it. Typically used with `pushd` and `dirs`.
843
844### dirs
845
846 dirs FLAG*
847
848Shows the contents of the directory stack. Typically used with `pushd` and
849`popd`.
850
851Flags:
852
853 -c Clear the dir stack.
854 -l Show the dir stack, but with the real path instead of ~.
855 -p Show the dir stack, but formatted as one line per entry.
856 -v Like -p, but numbering each line.
857
858## Completion
859
860These builtins implement our bash-compatible autocompletion system.
861
862### complete
863
864Registers completion policies for different commands.
865
866### compgen
867
868Generates completion candidates inside a user-defined completion function.
869
870It can also be used in scripts, i.e. outside a completion function.
871
872### compopt
873
874Changes completion options inside a user-defined completion function.
875
876### compadjust
877
878Adjusts `COMP_ARGV` according to specified delimiters, and optionally set
879variables cur, prev, words (an array), and cword. May also set 'split'.
880
881This is an OSH extension that makes it easier to run the bash-completion
882project.
883
884### compexport
885
886Complete an entire shell command string. For example,
887
888 compexport -c 'echo $H'
889
890will complete variables like `$HOME`. And
891
892 compexport -c 'ha'
893
894will complete builtins like `hay`, as well as external commands.
895
896
897## Shell Process
898
899These builtins mutate the state of the shell process.
900
901### exec
902
903 exec BIN_PATH ARG*
904
905Replaces the running shell with the binary specified, which is passed ARGs.
906BIN_PATH must exist on the file system; i.e. it can't be a shell builtin or
907function.
908
909### umask
910
911 umask MODE?
912
913Sets the bit mask that determines the permissions for new files and
914directories. The mask is subtracted from 666 for files and 777 for
915directories.
916
917Oils currently supports writing masks in octal.
918
919If no MODE, show the current mask.
920
921### ulimit
922
923 ulimit --all
924 ulimit -a
925 ulimit FLAGS* -RESOURCE_FLAG VALUE?
926
927 ulimit FLAGS* VALUE? # discouraged
928
929Show and modify process resource limits.
930
931Flags:
932
933 -S for soft limit
934 -H for hard limit
935
936 -c -d -f ... # ulimit --all shows all resource flags
937
938Show a table of resources:
939
940 ulimit --all
941 ulimit -a
942
943For example, the table shows that `-n` is the flag that controls the number
944file descriptors, the soft and hard limit for `-n`, and the multiplication
945"factor" for the integer VALUE you pass.
946
947---
948
949Here are examples of using resource flags.
950
951Get the soft limit for the number of file descriptors:
952
953 ulimit -S -n
954 ulimit -n # same thing
955
956Get the hard limit:
957
958 ulimit -H -n
959
960Set the soft or hard limit:
961
962 ulimit -S -n 100
963 ulimit -H -n 100
964
965Set both limits:
966
967 ulimit -n 100
968
969A special case that's discouraged: with no resource flag, `-f` is assumed:
970
971 ulimit # equivalent to ulimit -f
972 ulimit 100 # equivalent to ulimit -f 100
973
974### times
975
976 times
977
978Shows the user and system time used by the shell and its child processes.
979
980## Child Process
981
982### jobs
983
984 jobs
985
986Shows all jobs running in the shell and their status.
987
988### wait
989
990 wait FLAG* ARG
991
992Wait for processes to exit.
993
994If the ARG is a PID, wait only for that job, and return its status.
995
996If there's no ARG, wait for all child processes.
997
998<!--
999The ARG can be a PID (tracked by the kernel), or a job number (tracked by the
1000shell). Specify jobs with the syntax `%jobnumber`.
1001-->
1002
1003Flags:
1004
1005 -n Wait for the next process to exit, rather than a specific process.
1006
1007Wait can be interrupted by a signal, in which case the exit code indicates the
1008signal number.
1009
1010### fg
1011
1012 fg JOB?
1013
1014Returns a job running in the background to the foreground. If no JOB is
1015specified, use the latest job.
1016
1017<!--<h4 id="bg">bg</h4>
1018
1019The bg builtin resumes suspend job, while keeping it in the background.
1020
1021bg JOB?
1022
1023JOB:
1024 Job ID to be resumed in the background. If none is specified, the latest job
1025 is chosen. -->
1026
1027## External
1028
1029### test
1030
1031 test OP ARG
1032 test ARG OP ARG
1033 [ OP ARG ] # [ is an alias for test that requires closing ]
1034 [ ARG OP ARG ]
1035
1036Evaluates a conditional expression and returns 0 (true) or 1 (false).
1037
1038Note that [ is the name of a builtin, not an operator in the language. Use
1039'test' to avoid this confusion.
1040
1041String expressions:
1042
1043 -n STR True if STR is not empty.
1044 'test STR' is usually equivalent, but discouraged.
1045 -z STR True if STR is empty.
1046 STR1 = STR2 True if the strings are equal.
1047 STR1 != STR2 True if the strings are not equal.
1048 STR1 < STR2 True if STR1 sorts before STR2 lexicographically.
1049 STR1 > STR2 True if STR1 sorts after STR2 lexicographically.
1050 Note: < and > should be quoted like \< and \>
1051
1052File expressions:
1053
1054 -a FILE Synonym for -e.
1055 -b FILE True if FILE is a block special file.
1056 -c FILE True if FILE is a character special file.
1057 -d FILE True if FILE is a directory.
1058 -e FILE True if FILE exists.
1059 -f FILE True if FILE is a regular file.
1060 -g FILE True if FILE has the sgid bit set.
1061 -G FILE True if current user's group is also FILE's group.
1062 -h FILE True if FILE is a symbolic link.
1063 -L FILE True if FILE is a symbolic link.
1064 -k FILE True if FILE has the sticky bit set.
1065 -O FILE True if current user is the file owner.
1066 -p FILE True if FILE is a named pipe (FIFO).
1067 -r FILE True if FILE is readable.
1068 -s FILE True if FILE has size bigger than 0.
1069 -S FILE True if FILE is a socket file.
1070 -t FD True if file descriptor FD is open and refers to a terminal.
1071 -u FILE True if FILE has suid bit set.
1072 -w FILE True if FILE is writable.
1073 -x FILE True if FILE is executable.
1074 FILE1 -nt FILE2 True if FILE1 is newer than FILE2 (mtime).
1075 FILE1 -ot FILE2 True if FILE1 is older than FILE2 (mtime).
1076 FILE1 -ef FILE2 True if FILE1 is a hard link to FILE2.
1077<!-- -N FILE True if FILE was modified since last read (mtime newer than atime).-->
1078
1079Arithmetic expressions coerce arguments to integers, then compare:
1080
1081 INT1 -eq INT2 True if they're equal.
1082 INT1 -ne INT2 True if they're not equal.
1083 INT1 -lt INT2 True if INT1 is less than INT2.
1084 INT1 -le INT2 True if INT1 is less or equal than INT2.
1085 INT1 -gt INT2 True if INT1 is greater than INT2.
1086 INT1 -ge INT2 True if INT1 is greater or equal than INT2.
1087
1088Other expressions:
1089
1090 -o OPTION True if the shell option OPTION is set.
1091 -v VAR True if the variable VAR is set.
1092
1093The test builtin also supports POSIX conditionals like -a, -o, !, and ( ), but
1094these are discouraged.
1095
1096<!-- -R VAR True if the variable VAR has been set and is a nameref variable. -->
1097
1098Oils supports these long flags:
1099
1100 --dir same as -d
1101 --exists same as -e
1102 --file same as -f
1103 --symlink same as -L
1104
1105### getopts
1106
1107 getopts SPEC VAR ARG*
1108
1109A single iteration of flag parsing. The SPEC is a sequence of flag characters,
1110with a trailing `:` to indicate that the flag takes an argument:
1111
1112 ab # accept -a and -b
1113 xy:z # accept -x, -y arg, and -z
1114
1115The input is `"$@"` by default, unless ARGs are passed.
1116
1117On each iteration, the flag character is stored in VAR. If the flag has an
1118argument, it's stored in `$OPTARG`. When an error occurs, VAR is set to `?`
1119and `$OPTARG` is unset.
1120
1121Returns 0 if a flag is parsed, or 1 on end of input or another error.
1122
1123Example:
1124
1125 while getopts "ab:" flag; do
1126 case $flag in
1127 a) flag_a=1 ;;
1128 b) flag_b=$OPTARG" ;;
1129 '?') echo 'Invalid Syntax'; break ;;
1130 esac
1131 done
1132
1133Notes:
1134- `$OPTIND` is initialized to 1 every time a shell starts, and is used to
1135 maintain state between invocations of `getopts`.
1136- The characters `:` and `?` can't be flags.
1137
1138### kill
1139
1140Unimplemented.
1141
1142<!-- Note: 'kill' accepts job control syntax -->
1143
1144## Introspection
1145
1146<h3 id="help" class="osh-topic ysh-topic" oils-embed="1">
1147 help
1148</h3>
1149
1150<!-- pre-formatted for help builtin -->
1151
1152```
1153Usage: help TOPIC?
1154
1155Examples:
1156
1157 help # this help
1158 help echo # help on the 'echo' builtin
1159 help command-sub # help on command sub $(date)
1160
1161 help oils-usage # identical to oils-for-unix --help
1162 help osh-usage # osh --help
1163 help ysh-usage # ysh --help
1164```
1165
1166### hash
1167
1168 hash
1169
1170Display information about remembered commands.
1171
1172 hash FLAG* CMD+
1173
1174Determine the locations of commands using `$PATH`, and remember them.
1175
1176Flag:
1177
1178 -r Discard all remembered locations.
1179<!-- -d Discard the remembered location of each NAME.
1180 -l Display output in a format reusable as input.
1181 -p PATH Inhibit path search, PATH is used as location for NAME.
1182 -t Print the full path of one or more NAME.-->
1183
1184### cmd/type
1185
1186 type FLAG* NAME+
1187
1188Print the type of each NAME, if it were the first word of a command. Is it a
1189shell keyword, builtin command, shell function, alias, or executable file on
1190$PATH?
1191
1192Flags:
1193
1194 -a Show all possible candidates, not just the first one
1195 -f Don't search for shell functions
1196 -P Only search for executable files
1197 -t Print a single word: alias, builtin, file, function, or keyword
1198
1199Similar names: [type][]
1200
1201[type]: chap-index.html#type
1202
1203<!-- TODO:
1204- procs are counted as shell functions, should be their own thing
1205- Hay nodes ('hay define x') also live in the first word namespace, and should
1206 be recognized
1207-->
1208
1209Modeled after the [bash `type`
1210builtin](https://www.gnu.org/software/bash/manual/bash.html#index-type).
1211
1212## Word Lookup
1213
1214### command
1215
1216 command FLAG* CMD ARG*
1217
1218Look up CMD as a shell builtin or executable file, and execute it with the
1219given ARGs. That is, the lookup ignores shell functions named CMD.
1220
1221Flags:
1222
1223 -v Instead of executing CMD, print a description of it.
1224 Similar to the 'type' builtin.
1225<!-- -p Use a default value for PATH that is guaranteed to find all of the
1226 standard utilities.
1227 -V Print a more verbose description of CMD.-->
1228
1229### builtin
1230
1231 builtin CMD ARG*
1232
1233Look up CMD as a shell builtin, and execute it with the given ARGs. That is,
1234the lookup ignores shell functions and executables named CMD.
1235
1236## Interactive
1237
1238### alias
1239
1240 alias NAME=CODE
1241
1242Make NAME a shortcut for executing CODE, e.g. `alias hi='echo hello'`.
1243
1244 alias NAME
1245
1246Show the value of this alias.
1247
1248 alias
1249
1250Show a list of all aliases.
1251
1252Tips:
1253
1254Prefer shell functions like:
1255
1256 ls() {
1257 command ls --color "$@"
1258 }
1259
1260to aliases like:
1261
1262 alias ls='ls --color'
1263
1264Functions are less likely to cause parsing problems.
1265
1266- Quoting like `\ls` or `'ls'` disables alias expansion
1267- To remove an existing alias, use [unalias](chap-builtin-cmd.html#unalias).
1268
1269### unalias
1270
1271 unalias NAME
1272
1273Remove the alias NAME.
1274
1275<!--Flag:
1276
1277 -a Removes all existing aliases.-->
1278
1279### history
1280
1281 history FLAG*
1282
1283Display and manipulate the shell's history entries.
1284
1285 history NUM
1286
1287Show the last NUM history entries.
1288
1289Flags:
1290
1291 -c Clears the history.
1292 -d POS Deletes the history entry at position POS.
1293<!-- -a
1294 -n
1295 -r
1296 -w
1297 -p
1298 -s -->
1299
1300
1301## Unsupported
1302
1303### enable
1304
1305Bash has this, but OSH won't implement it.
1306
1307
1308## Args Parser
1309
1310YSH includes a command-line argument parsing utility called `parseArgs`. This
1311is intended to be used for command-line interfaces to YSH programs.
1312
1313To use it, first import `args.ysh`:
1314
1315 source --builtin args.ysh
1316
1317Then, create an argument parser **spec**ification:
1318
1319 parser (&spec) {
1320 flag -v --verbose (help="Verbosely") # default is Bool, false
1321
1322 flag -P --max-procs ('int', default=-1, help='''
1323 Run at most P processes at a time
1324 ''')
1325
1326 flag -i --invert ('bool', default=true, help='''
1327 Long multiline
1328 Description
1329 ''')
1330
1331 arg src (help='Source')
1332 arg dest (help='Dest')
1333
1334 rest files
1335 }
1336
1337Finally, parse `ARGV` (or any other array of strings) with:
1338
1339 var args = parseArgs(spec, ARGV)
1340
1341The returned `args` is a `Dict` containing key-value pairs with the parsed
1342values (or defaults) for each flag and argument. For example, given
1343`ARGV = :| mysrc -P 12 mydest a b c |`, `args` would be:
1344
1345 {
1346 "verbose": false,
1347 "max-procs": 12,
1348 "invert": true,
1349 "src": "mysrc",
1350 "dest": "mydest",
1351 "files": ["a", "b", "c"]
1352 }
1353
1354### parser
1355
1356`parseArgs()` requires a parser specification to indicate how to parse the
1357`ARGV` array. This specification should be constructed using the `parser` proc.
1358
1359 parser (&spec) {
1360 flag -f --my-flag
1361 arg myarg
1362 rest otherArgs
1363 }
1364
1365In the above example, `parser` takes in a place `&spec`, which will store the
1366resulting specification and a block which is evaluated to build that
1367specification.
1368
1369Inside of a `parser` block, you should call the following procs:
1370
1371- `flag` to add `--flag` options
1372- `arg` to add positional arguments
1373- `rest` to capture remaining positional arguments into a list
1374
1375`parser` will validate the parser specification for errors such as duplicate
1376flag or argument names.
1377
1378 parser (&spec) {
1379 flag -n --name
1380 flag -n --name # Duplicate!
1381 }
1382
1383 # => raises "Duplicate flag/arg name 'name' in spec" (status = 3)
1384
1385### flag
1386
1387`flag` should be called within a `parser` block.
1388
1389 parser (&spec) {
1390 flag -v --verbose
1391 }
1392
1393The above example declares a flag "--verbose" and a short alias "-v".
1394`parseArgs()` will then store a boolean value under `args.verbose`:
1395- `true` if the flag was passed at least once
1396- `false` otherwise
1397
1398Flags can also accept values. For example, if you wanted to accept an integer count:
1399
1400 parser (&spec) {
1401 flag -N --count ('int')
1402 }
1403
1404Calling `parseArgs` with `ARGV = :| -n 5 |` or `ARGV = :| --count 5 |` will
1405store the integer `5` under `args.count`. If the user passes in a non-integer
1406value like `ARGV = :| --count abc |`, `parseArgs` will raise an error.
1407
1408Default values for an argument can be set with the `default` named argument.
1409
1410 parser (&spec) {
1411 flag -N --count ('int', default=2)
1412
1413 # Boolean flags can be given default values too
1414 flag -O --optimize ('bool', default=true)
1415 }
1416
1417 var args = parseArgs(spec, :| -n 3 |)
1418 # => args.count = 2
1419 # => args.optimize = true
1420
1421Each name passed to `flag` must be unique to that specific `parser`. Calling
1422`flag` with the same name twice will raise an error inside of `parser`.
1423
1424<!-- TODO: how can we explicitly pass false to a boolean flag? -->
1425<!-- TODO: how about --no-XXXX variants of flags? -->
1426
1427### arg
1428
1429`arg` should be called within a `parser` block.
1430
1431 parser (&spec) {
1432 arg query
1433 arg path
1434 }
1435
1436The above example declares two positional arguments called "query" and "path".
1437`parseArgs()` will then store strings under `args.query` and `args.path`. Order
1438matters, so the first positional argument will be stored to `query` and the
1439second to `path`. If not enough positional arguments are passed, then
1440`parseArgs` will raise an error.
1441
1442Similar to `flag`, each `arg` name must be unique. Calling `arg` with the same
1443name twice will cause `parser` to raise an error.
1444
1445### rest
1446
1447`rest` should be called within a `parser` block.
1448
1449 parser (&spec) {
1450 arg query
1451 rest files
1452 }
1453
1454Capture zero or more positional arguments not already captured by `arg`. So,
1455for `ARGV = :| hello file.txt message.txt README.md |`, we would have
1456`args.query = "file.txt"` and `args.files = ["file.txt", "message.txt",
1457"README.md"]`.
1458
1459Without rest, passing extraneous arguments will raise an error in
1460`parseArgs()`.
1461
1462`rest` can only be called _once_ within a `parser`. Calling it multiple times
1463will raise an error in `parser`.
1464
1465### parseArgs()
1466
1467Given a parser specification `spec` produced by `parser`, parse a list of
1468strings (usually `ARGV`.)
1469
1470 var args = parseArgs(spec, ARGV)
1471
1472The returned `args` is a dictionary mapping the names of each `arg`, `flag` and
1473`rest` to their captured values. (See the example at the [start of this
1474topic](#Args-Parser).)
1475
1476`parseArgs` will raise an error if the `ARGV` is invalid per the parser
1477specification. For example, if it's missing a required positional argument:
1478
1479 parser (&spec) {
1480 arg path
1481 }
1482
1483 var args = parseArgs(spec, [])
1484 # => raises an error about the missing 'path' (status = 2)
1485
1486<!--
1487TODO: Document chaining parsers / sub-commands
1488 - Either will allow parser nesting
1489 - Or can use `rest rest` and `parseArgs` again on `rest`
1490TODO: Document the help named argument. Punting while we do not generate help messages
1491-->