1 ## oils_failures_allowed: 1
2 ## compare_shells: dash bash mksh zsh
3
4 #### command -v
5 myfunc() { echo x; }
6 command -v echo
7 echo $?
8
9 command -v myfunc
10 echo $?
11
12 command -v nonexistent # doesn't print anything
13 echo nonexistent=$?
14
15 command -v '' # BUG FIX, shouldn't succeed
16 echo empty=$?
17
18 command -v for
19 echo $?
20
21 ## STDOUT:
22 echo
23 0
24 myfunc
25 0
26 nonexistent=1
27 empty=1
28 for
29 0
30 ## OK dash STDOUT:
31 echo
32 0
33 myfunc
34 0
35 nonexistent=127
36 empty=127
37 for
38 0
39 ## END
40
41 #### command -v with multiple names
42 # ALL FOUR SHELLS behave differently here!
43 #
44 # bash chooses to swallow the error! We agree with zsh if ANY word lookup
45 # fails, then the whole thing fails.
46
47 myfunc() { echo x; }
48 command -v echo myfunc ZZZ for
49 echo status=$?
50
51 ## STDOUT:
52 echo
53 myfunc
54 for
55 status=1
56 ## BUG bash STDOUT:
57 echo
58 myfunc
59 for
60 status=0
61 ## BUG dash STDOUT:
62 echo
63 status=0
64 ## OK mksh STDOUT:
65 echo
66 myfunc
67 status=1
68 ## END
69
70 #### command -v doesn't find non-executable file
71 # PATH resolution is different
72
73 PATH="_tmp:$PATH"
74 touch _tmp/non-executable _tmp/executable
75 chmod +x _tmp/executable
76
77 command -v _tmp/non-executable
78 echo status=$?
79
80 command -v _tmp/executable
81 echo status=$?
82
83 ## STDOUT:
84 status=1
85 _tmp/executable
86 status=0
87 ## END
88
89 ## BUG dash STDOUT:
90 _tmp/non-executable
91 status=0
92 _tmp/executable
93 status=0
94 ## END
95
96 #### command -V
97 myfunc() { echo x; }
98
99 shopt -s expand_aliases
100 alias ll='ls -l'
101
102 backtick=\`
103 command -V ll | sed "s/$backtick/'/g"
104 echo status=$?
105
106 command -V echo
107 echo status=$?
108
109 command -V myfunc
110 echo status=$?
111
112 command -V nonexistent # doesn't print anything
113 echo status=$?
114
115 command -V for
116 echo status=$?
117
118 ## STDOUT:
119 ll is an alias for "ls -l"
120 status=0
121 echo is a shell builtin
122 status=0
123 myfunc is a shell function
124 status=0
125 status=1
126 for is a shell keyword
127 status=0
128 ## END
129
130 ## OK zsh STDOUT:
131 ll is an alias for ls -l
132 status=0
133 echo is a shell builtin
134 status=0
135 myfunc is a shell function
136 status=0
137 nonexistent not found
138 status=1
139 for is a reserved word
140 status=0
141 ## END
142
143 ## OK bash STDOUT:
144 ll is aliased to 'ls -l'
145 status=0
146 echo is a shell builtin
147 status=0
148 myfunc is a function
149 myfunc ()
150 {
151 echo x
152 }
153 status=0
154 status=1
155 for is a shell keyword
156 status=0
157 ## END
158
159 ## OK mksh STDOUT:
160 ll is an alias for 'ls -l'
161 status=0
162 echo is a shell builtin
163 status=0
164 myfunc is a function
165 status=0
166 nonexistent not found
167 status=1
168 for is a reserved word
169 status=0
170 ## END
171
172 ## OK dash STDOUT:
173 ll is an alias for ls -l
174 status=0
175 echo is a shell builtin
176 status=0
177 myfunc is a shell function
178 status=0
179 nonexistent: not found
180 status=127
181 for is a shell keyword
182 status=0
183 ## END
184
185 #### command -V nonexistent
186 command -V nonexistent 2>err.txt
187 echo status=$?
188 fgrep -o 'nonexistent: not found' err.txt || true
189
190 ## STDOUT:
191 status=1
192 nonexistent: not found
193 ## END
194
195 ## OK zsh/mksh STDOUT:
196 nonexistent not found
197 status=1
198 ## END
199
200 ## BUG dash STDOUT:
201 nonexistent: not found
202 status=127
203 ## END
204
205
206 #### command skips function lookup
207 seq() {
208 echo "$@"
209 }
210 command # no-op
211 seq 3
212 command seq 3
213 # subshell shouldn't fork another process (but we don't have a good way of
214 # testing it)
215 ( command seq 3 )
216 ## STDOUT:
217 3
218 1
219 2
220 3
221 1
222 2
223 3
224 ## END
225
226 #### command command seq 3
227 command command seq 3
228 ## STDOUT:
229 1
230 2
231 3
232 ## END
233 ## N-I zsh stdout-json: ""
234 ## N-I zsh status: 127
235
236 #### command command -v seq
237 seq() {
238 echo 3
239 }
240 command command -v seq
241 ## stdout: seq
242 ## N-I zsh stdout-json: ""
243 ## N-I zsh status: 127
244
245 #### command -p (override existing program)
246 # Tests whether command -p overrides the path
247 # tr chosen because we need a simple non-builtin
248 mkdir -p $TMP/bin
249 echo "echo wrong" > $TMP/bin/tr
250 chmod +x $TMP/bin/tr
251 PATH="$TMP/bin:$PATH"
252 echo aaa | tr "a" "b"
253 echo aaa | command -p tr "a" "b"
254 rm $TMP/bin/tr
255 ## STDOUT:
256 wrong
257 bbb
258 ## END
259
260 #### command -p (hide tool in custom path)
261 mkdir -p $TMP/bin
262 echo "echo hello" > $TMP/bin/hello
263 chmod +x $TMP/bin/hello
264 export PATH=$TMP/bin
265 command -p hello
266 ## status: 127
267
268 #### command -p (find hidden tool in default path)
269 export PATH=''
270 command -p ls
271 ## status: 0
272
273
274 #### $(command type ls)
275 type() { echo FUNCTION; }
276 type
277 s=$(command type echo)
278 echo $s | grep builtin > /dev/null
279 echo status=$?
280 ## STDOUT:
281 FUNCTION
282 status=0
283 ## END
284 ## N-I zsh STDOUT:
285 FUNCTION
286 status=1
287 ## END
288 ## N-I mksh STDOUT:
289 status=1
290 ## END
291
292 #### builtin
293 cd () { echo "hi"; }
294 cd
295 builtin cd / && pwd
296 unset -f cd
297 ## STDOUT:
298 hi
299 /
300 ## END
301 ## N-I dash STDOUT:
302 hi
303 ## END
304
305 #### builtin ls not found
306 builtin ls
307 ## status: 1
308 ## N-I dash status: 127
309
310 #### builtin no args
311 builtin
312 ## status: 0
313 ## N-I dash status: 127
314
315 #### builtin command echo hi
316 builtin command echo hi
317 ## status: 0
318 ## stdout: hi
319 ## N-I dash status: 127
320 ## N-I dash stdout-json: ""
321
322 #### builtin typeset / export / readonly
323 case $SH in dash) exit ;; esac
324
325 builtin typeset s=typeset
326 echo s=$s
327
328 builtin export s=export
329 echo s=$s
330
331 builtin readonly s=readonly
332 echo s=$s
333
334 echo --
335
336 builtin builtin typeset s2=typeset
337 echo s2=$s2
338
339 builtin builtin export s2=export
340 echo s2=$s2
341
342 builtin builtin readonly s2=readonly
343 echo s2=$s2
344
345 ## STDOUT:
346 s=typeset
347 s=export
348 s=readonly
349 --
350 s2=typeset
351 s2=export
352 s2=readonly
353 ## END
354 ## N-I dash STDOUT:
355 ## END
356
357 #### builtin declare / local
358 case $SH in dash|mksh) exit ;; esac
359
360 builtin declare s=declare
361 echo s=$s
362
363 f() {
364 builtin local s=local
365 echo s=$s
366 }
367
368 f
369
370 ## STDOUT:
371 s=declare
372 s=local
373 ## END
374 ## N-I dash/mksh STDOUT:
375 ## END
376
377 #### builtin declare a=(x y) etc.
378
379 $SH -c 'builtin declare a=(x y)'
380 if test $? -ne 0; then
381 echo 'fail'
382 fi
383
384 $SH -c 'builtin declare -a a=(x y)'
385 if test $? -ne 0; then
386 echo 'fail'
387 fi
388
389 ## STDOUT:
390 fail
391 fail
392 ## END
393
394 ## OK osh STDOUT:
395 ## END
396
397
398 #### command export / readonly
399 case $SH in zsh) exit ;; esac
400
401 # dash doesn't have declare typeset
402
403 command export c=export
404 echo c=$c
405
406 command readonly c=readonly
407 echo c=$c
408
409 echo --
410
411 command command export cc=export
412 echo cc=$cc
413
414 command command readonly cc=readonly
415 echo cc=$cc
416
417 ## STDOUT:
418 c=export
419 c=readonly
420 --
421 cc=export
422 cc=readonly
423 ## END
424 ## N-I zsh STDOUT:
425 ## END
426
427 #### command local
428
429 f() {
430 command local s=local
431 echo s=$s
432 }
433
434 f
435
436 ## STDOUT:
437 s=local
438 ## END
439 ## BUG dash/mksh/zsh STDOUT:
440 s=
441 ## END
442
443
444 #### static builtin command ASSIGN, command builtin ASSIGN
445 case $SH in dash|zsh) exit ;; esac
446
447 # dash doesn't have declare typeset
448
449 builtin command export bc=export
450 echo bc=$bc
451
452 builtin command readonly bc=readonly
453 echo bc=$bc
454
455 echo --
456
457 command builtin export cb=export
458 echo cb=$cb
459
460 command builtin readonly cb=readonly
461 echo cb=$cb
462
463 ## STDOUT:
464 bc=export
465 bc=readonly
466 --
467 cb=export
468 cb=readonly
469 ## END
470 ## N-I dash/zsh STDOUT:
471 ## END
472
473 #### dynamic builtin command ASSIGN, command builtin ASSIGN
474 case $SH in dash|zsh) exit ;; esac
475
476 b=builtin
477 c=command
478 e=export
479 r=readonly
480
481 $b $c export bc=export
482 echo bc=$bc
483
484 $b $c readonly bc=readonly
485 echo bc=$bc
486
487 echo --
488
489 $c $b export cb=export
490 echo cb=$cb
491
492 $c $b readonly cb=readonly
493 echo cb=$cb
494
495 echo --
496
497 $b $c $e bce=export
498 echo bce=$bce
499
500 $b $c $r bcr=readonly
501 echo bcr=$bcr
502
503 echo --
504
505 $c $b $e cbe=export
506 echo cbe=$cbe
507
508 $c $b $r cbr=readonly
509 echo cbr=$cbr
510
511 ## STDOUT:
512 bc=export
513 bc=readonly
514 --
515 cb=export
516 cb=readonly
517 --
518 bce=export
519 bcr=readonly
520 --
521 cbe=export
522 cbr=readonly
523 ## END
524 ## N-I dash/zsh STDOUT:
525 ## END
526
527
528 #### Assignment builtins and word splitting, even after builtin/command
529
530 x='a b'
531
532 readonly y=$x
533 echo $x
534
535 command readonly z=$x
536 echo $z
537
538 ## STDOUT:
539 a b
540 a b
541 ## END
542
543 ## BUG dash/bash STDOUT:
544 a b
545 a
546 ## END
547
548 ## N-I zsh STDOUT:
549 a b
550
551 ## END
552
553 #### More word splitting
554
555 x='a b'
556
557 export y=$x
558 echo $y
559
560 builtin export z=$x
561 echo $z
562
563 ## STDOUT:
564 a b
565 a b
566 ## END
567
568 ## BUG bash/mksh STDOUT:
569 a b
570 a
571 ## END
572
573 ## N-I dash STDOUT:
574 a
575
576 ## END
577
578 #### \builtin declare - ble.sh relies on it
579
580 # \command readonly is equivalent to \builtin declare
581 # except dash implements it
582
583 x='a b'
584
585 command readonly y=$x
586 echo $y
587
588 \command readonly z=$x
589 echo $z
590
591 # The issue here is that we have a heuristic in EvalWordSequence2:
592 # fs len(part_vals) == 1
593
594 ## STDOUT:
595 a b
596 a b
597 ## END
598
599 ## OK bash/dash STDOUT:
600 a
601 a
602 ## END
603
604 ## N-I zsh STDOUT:
605
606
607 ## END