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

1495 lines, 963 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
644 reusable 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
650 (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
660 named in the argument.
661 %a Interprets the argument as double, and prints it like a C99
662 hexadecimal 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
665 string for strftime(3). The argument is the number of
666 seconds since epoch. It can also be -1 (current time,
667 also the default value if there is no argument) or -2
668 (shell startup time).
669
670### readarray
671
672Alias for `mapfile`.
673
674### mapfile
675
676 mapfile FLAG* ARRAY?
677
678Reads lines from stdin into the variable named ARRAY (default
679`${MAPFILE[@]}`).
680
681Flags:
682
683 -t Remove the trailing newline from every line
684<!--
685 -d CHAR use CHAR as delimiter, instead of the default newline
686 -n NUM copy up to NUM lines
687 -O NUM begins copying lines at the NUM element of the array
688 -s NUM discard the first NUM lines
689 -u FD read from FD file descriptor instead of the standard input
690 -C CMD run CMD every NUM lines specified in -c
691 -c NUM every NUM lines, the CMD command in C will be run
692-->
693
694## Run Code
695
696These builtins accept shell code and run it.
697
698### source
699
700 source SCRIPT ARG*
701
702Executes SCRIPT with given ARGs in the context of the current shell. It will
703modify existing variables.
704
705### eval
706
707 eval ARG+
708
709Creates a string by joining ARGs with a space, then runs it as a shell command.
710
711Example:
712
713 # Create the string echo "hello $name" and run it.
714 a='echo'
715 b='"hello $name"'
716 eval $a $b
717
718Tips:
719
720- Using `eval` can confuse code and user-supplied data, leading to [security
721issues][].
722- Prefer passing single string ARG to `eval`.
723
724[security issues]: https://mywiki.wooledge.org/BashFAQ/048
725
726YSH eval:
727
728 var myblock = ^(echo hi)
729 eval (myblock) # => hi
730
731
732### trap
733
734 trap FLAG* CMD SIGNAL*
735
736Registers the shell string CMD to be run after the SIGNALs are received. If
737the CMD is empty, then the signal is ignored.
738
739Flags:
740
741 -l Lists all signals and their signal number
742 -p Prints a list of the installed signal handlers
743
744Tip:
745
746Prefer passing the name of a shell function to `trap`.
747
748## Set Options
749
750The `set` and `shopt` builtins set global shell options. YSH code should use
751the more natural `shopt`.
752
753### set
754
755 set FLAG* ARG*
756
757Sets global shell options. Short style:
758
759 set -e
760
761Long style:
762
763 set -o errexit
764
765Set the arguments array:
766
767 set -- 1 2 3
768
769### shopt
770
771 shopt FLAG* OPTION* BLOCK?
772
773Sets global shell options.
774
775Flags:
776
777 -s --set Turn the named options on
778 -u --unset Turn the named options off
779 -p Print option values
780 -o Use older set of options, normally controlled by 'set -o'
781 -q Return 0 if the option is true, else 1
782
783Examples:
784
785 shopt --set errexit
786
787You can set or unset multiple options with the groups `strict:all`,
788`ysh:upgrade`, and `ysh:all`.
789
790If a block is passed, then the mutated options are pushed onto a stack, the
791block is executed, and then options are restored to their original state.
792
793## Working Dir
794
795These 5 builtins deal with the working directory of the shell.
796
797### cd
798
799 cd FLAG* DIR
800
801Changes the working directory of the current shell process to DIR.
802
803If DIR isn't specified, change to `$HOME`. If DIR is `-`, change to `$OLDPWD`
804(a variable that the sets to the previous working directory.)
805
806Flags:
807
808 -L Follow symbolic links, i.e. change to the TARGET of the symlink.
809 (default).
810 -P Don't follow symbolic links.
811
812### pwd
813
814 pwd FLAG*
815
816Prints the current working directory.
817
818Flags:
819
820 -L Follow symbolic links if present (default)
821 -P Don't follow symbolic links.
822 Print the link instead of the target.
823
824### pushd
825
826<!--pushd FLAGS DIR-->
827 pushd DIR
828<!--pushd +/-NUM-->
829
830Add DIR to the directory stack, then change the working directory to DIR.
831Typically used with `popd` and `dirs`.
832
833<!--FLAGS:
834 -n Don't change the working directory, just manipulate the stack
835NUM:
836 Rotates the stack the number of places specified. Eg, given the stack
837 '/foo /bar /baz', where '/foo' is the top of the stack, pushd +1 will move
838 it to the bottom, '/bar /baz /foo'-->
839
840### popd
841
842 popd
843
844Removes a directory from the directory stack, and changes the working directory
845to it. Typically used with `pushd` and `dirs`.
846
847### dirs
848
849 dirs FLAG*
850
851Shows the contents of the directory stack. Typically used with `pushd` and
852`popd`.
853
854Flags:
855
856 -c Clear the dir stack.
857 -l Show the dir stack, but with the real path instead of ~.
858 -p Show the dir stack, but formatted as one line per entry.
859 -v Like -p, but numbering each line.
860
861## Completion
862
863These builtins implement our bash-compatible autocompletion system.
864
865### complete
866
867Registers completion policies for different commands.
868
869### compgen
870
871Generates completion candidates inside a user-defined completion function.
872
873It can also be used in scripts, i.e. outside a completion function.
874
875### compopt
876
877Changes completion options inside a user-defined completion function.
878
879### compadjust
880
881Adjusts `COMP_ARGV` according to specified delimiters, and optionally set
882variables cur, prev, words (an array), and cword. May also set 'split'.
883
884This is an OSH extension that makes it easier to run the bash-completion
885project.
886
887### compexport
888
889Complete an entire shell command string. For example,
890
891 compexport -c 'echo $H'
892
893will complete variables like `$HOME`. And
894
895 compexport -c 'ha'
896
897will complete builtins like `hay`, as well as external commands.
898
899
900## Shell Process
901
902These builtins mutate the state of the shell process.
903
904### exec
905
906 exec BIN_PATH ARG*
907
908Replaces the running shell with the binary specified, which is passed ARGs.
909BIN_PATH must exist on the file system; i.e. it can't be a shell builtin or
910function.
911
912### umask
913
914 umask MODE?
915
916Sets the bit mask that determines the permissions for new files and
917directories. The mask is subtracted from 666 for files and 777 for
918directories.
919
920Oils currently supports writing masks in octal.
921
922If no MODE, show the current mask.
923
924### ulimit
925
926 ulimit --all
927 ulimit -a
928 ulimit FLAGS* -RESOURCE_FLAG VALUE?
929
930 ulimit FLAGS* VALUE? # discouraged
931
932Show and modify process resource limits.
933
934Flags:
935
936 -S for soft limit
937 -H for hard limit
938
939 -c -d -f ... # ulimit --all shows all resource flags
940
941Show a table of resources:
942
943 ulimit --all
944 ulimit -a
945
946For example, the table shows that `-n` is the flag that controls the number
947file descriptors, the soft and hard limit for `-n`, and the multiplication
948"factor" for the integer VALUE you pass.
949
950---
951
952Here are examples of using resource flags.
953
954Get the soft limit for the number of file descriptors:
955
956 ulimit -S -n
957 ulimit -n # same thing
958
959Get the hard limit:
960
961 ulimit -H -n
962
963Set the soft or hard limit:
964
965 ulimit -S -n 100
966 ulimit -H -n 100
967
968Set both limits:
969
970 ulimit -n 100
971
972A special case that's discouraged: with no resource flag, `-f` is assumed:
973
974 ulimit # equivalent to ulimit -f
975 ulimit 100 # equivalent to ulimit -f 100
976
977### times
978
979 times
980
981Shows the user and system time used by the shell and its child processes.
982
983## Child Process
984
985### jobs
986
987 jobs
988
989Shows all jobs running in the shell and their status.
990
991### wait
992
993 wait FLAG* ARG
994
995Wait for processes to exit.
996
997If the ARG is a PID, wait only for that job, and return its status.
998
999If there's no ARG, wait for all child processes.
1000
1001<!--
1002The ARG can be a PID (tracked by the kernel), or a job number (tracked by the
1003shell). Specify jobs with the syntax `%jobnumber`.
1004-->
1005
1006Flags:
1007
1008 -n Wait for the next process to exit, rather than a specific process.
1009
1010Wait can be interrupted by a signal, in which case the exit code indicates the
1011signal number.
1012
1013### fg
1014
1015 fg JOB?
1016
1017Returns a job running in the background to the foreground. If no JOB is
1018specified, use the latest job.
1019
1020<!--<h4 id="bg">bg</h4>
1021
1022The bg builtin resumes suspend job, while keeping it in the background.
1023
1024bg JOB?
1025
1026JOB:
1027 Job ID to be resumed in the background. If none is specified, the latest job
1028 is chosen. -->
1029
1030## External
1031
1032### test
1033
1034 test OP ARG
1035 test ARG OP ARG
1036 [ OP ARG ] # [ is an alias for test that requires closing ]
1037 [ ARG OP ARG ]
1038
1039Evaluates a conditional expression and returns 0 (true) or 1 (false).
1040
1041Note that [ is the name of a builtin, not an operator in the language. Use
1042'test' to avoid this confusion.
1043
1044String expressions:
1045
1046 -n STR True if STR is not empty.
1047 'test STR' is usually equivalent, but discouraged.
1048 -z STR True if STR is empty.
1049 STR1 = STR2 True if the strings are equal.
1050 STR1 != STR2 True if the strings are not equal.
1051 STR1 < STR2 True if STR1 sorts before STR2 lexicographically.
1052 STR1 > STR2 True if STR1 sorts after STR2 lexicographically.
1053 Note: < and > should be quoted like \< and \>
1054
1055File expressions:
1056
1057 -a FILE Synonym for -e.
1058 -b FILE True if FILE is a block special file.
1059 -c FILE True if FILE is a character special file.
1060 -d FILE True if FILE is a directory.
1061 -e FILE True if FILE exists.
1062 -f FILE True if FILE is a regular file.
1063 -g FILE True if FILE has the sgid bit set.
1064 -G FILE True if current user's group is also FILE's group.
1065 -h FILE True if FILE is a symbolic link.
1066 -L FILE True if FILE is a symbolic link.
1067 -k FILE True if FILE has the sticky bit set.
1068 -O FILE True if current user is the file owner.
1069 -p FILE True if FILE is a named pipe (FIFO).
1070 -r FILE True if FILE is readable.
1071 -s FILE True if FILE has size bigger than 0.
1072 -S FILE True if FILE is a socket file.
1073 -t FD True if file descriptor FD is open and refers to a
1074 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-->