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

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