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

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