1 ## compare_shells: dash bash mksh zsh ash
2
3 #### command -v
4 myfunc() { echo x; }
5 command -v echo
6 echo $?
7
8 command -v myfunc
9 echo $?
10
11 command -v nonexistent # doesn't print anything
12 echo nonexistent=$?
13
14 command -v '' # BUG FIX, shouldn't succeed
15 echo empty=$?
16
17 command -v for
18 echo $?
19
20 ## STDOUT:
21 echo
22 0
23 myfunc
24 0
25 nonexistent=1
26 empty=1
27 for
28 0
29 ## OK dash/ash STDOUT:
30 echo
31 0
32 myfunc
33 0
34 nonexistent=127
35 empty=127
36 for
37 0
38 ## END
39
40 #### command -v executable, builtin
41
42 #command -v grep ls
43
44 command -v grep | egrep -o '/[^/]+$'
45 command -v ls | egrep -o '/[^/]+$'
46 echo
47
48 command -v true
49 command -v eval
50
51 ## STDOUT:
52 /grep
53 /ls
54
55 true
56 eval
57 ## END
58
59
60 #### command -v with multiple names
61 # ALL FOUR SHELLS behave differently here!
62 #
63 # bash chooses to swallow the error! We agree with zsh if ANY word lookup
64 # fails, then the whole thing fails.
65
66 myfunc() { echo x; }
67 command -v echo myfunc ZZZ for
68 echo status=$?
69
70 ## STDOUT:
71 echo
72 myfunc
73 for
74 status=1
75 ## BUG bash STDOUT:
76 echo
77 myfunc
78 for
79 status=0
80 ## BUG dash/ash STDOUT:
81 echo
82 status=0
83 ## OK mksh STDOUT:
84 echo
85 myfunc
86 status=1
87 ## END
88
89 #### command -v doesn't find non-executable file
90 # PATH resolution is different
91
92 mkdir -p _tmp
93 PATH="_tmp:$PATH"
94 touch _tmp/non-executable _tmp/executable
95 chmod +x _tmp/executable
96
97 command -v _tmp/non-executable
98 echo status=$?
99
100 command -v _tmp/executable
101 echo status=$?
102
103 ## STDOUT:
104 status=1
105 _tmp/executable
106 status=0
107 ## END
108
109 ## BUG dash/ash STDOUT:
110 _tmp/non-executable
111 status=0
112 _tmp/executable
113 status=0
114 ## END
115
116 #### command -V
117 myfunc() { echo x; }
118
119 shopt -s expand_aliases
120 alias ll='ls -l'
121
122 backtick=\`
123 command -V ll | sed "s/$backtick/'/g"
124 echo status=$?
125
126 command -V echo
127 echo status=$?
128
129 # Paper over insignificant difference
130 command -V myfunc | sed 's/shell function/function/'
131 echo status=$?
132
133 command -V nonexistent # doesn't print anything
134 echo status=$?
135
136 command -V for
137 echo status=$?
138
139 ## STDOUT:
140 ll is an alias for "ls -l"
141 status=0
142 echo is a shell builtin
143 status=0
144 myfunc is a function
145 status=0
146 status=1
147 for is a shell keyword
148 status=0
149 ## END
150
151 ## OK zsh STDOUT:
152 ll is an alias for ls -l
153 status=0
154 echo is a shell builtin
155 status=0
156 myfunc is a function
157 status=0
158 nonexistent not found
159 status=1
160 for is a reserved word
161 status=0
162 ## END
163
164 ## OK bash STDOUT:
165 ll is aliased to 'ls -l'
166 status=0
167 echo is a shell builtin
168 status=0
169 myfunc is a function
170 myfunc ()
171 {
172 echo x
173 }
174 status=0
175 status=1
176 for is a shell keyword
177 status=0
178 ## END
179
180 ## OK mksh STDOUT:
181 ll is an alias for 'ls -l'
182 status=0
183 echo is a shell builtin
184 status=0
185 myfunc is a function
186 status=0
187 nonexistent not found
188 status=1
189 for is a reserved word
190 status=0
191 ## END
192
193 ## OK dash/ash STDOUT:
194 ll is an alias for ls -l
195 status=0
196 echo is a shell builtin
197 status=0
198 myfunc is a function
199 status=0
200 nonexistent: not found
201 status=127
202 for is a shell keyword
203 status=0
204 ## END
205
206 #### command -V nonexistent
207 command -V nonexistent 2>err.txt
208 echo status=$?
209 fgrep -o 'nonexistent: not found' err.txt || true
210
211 ## STDOUT:
212 status=1
213 nonexistent: not found
214 ## END
215
216 ## OK zsh/mksh STDOUT:
217 nonexistent not found
218 status=1
219 ## END
220
221 ## BUG dash/ash STDOUT:
222 nonexistent: not found
223 status=127
224 ## END
225
226
227 #### command skips function lookup
228 seq() {
229 echo "$@"
230 }
231 command # no-op
232 seq 3
233 command seq 3
234 # subshell shouldn't fork another process (but we don't have a good way of
235 # testing it)
236 ( command seq 3 )
237 ## STDOUT:
238 3
239 1
240 2
241 3
242 1
243 2
244 3
245 ## END
246
247 #### command command seq 3
248 command command seq 3
249 ## STDOUT:
250 1
251 2
252 3
253 ## END
254 ## N-I zsh stdout-json: ""
255 ## N-I zsh status: 127
256
257 #### command command -v seq
258 seq() {
259 echo 3
260 }
261 command command -v seq
262 ## stdout: seq
263 ## N-I zsh stdout-json: ""
264 ## N-I zsh status: 127
265
266 #### command -p (override existing program)
267 # Tests whether command -p overrides the path
268 # tr chosen because we need a simple non-builtin
269 mkdir -p $TMP/bin
270 echo "echo wrong" > $TMP/bin/tr
271 chmod +x $TMP/bin/tr
272 PATH="$TMP/bin:$PATH"
273 echo aaa | tr "a" "b"
274 echo aaa | command -p tr "a" "b"
275 rm $TMP/bin/tr
276 ## STDOUT:
277 wrong
278 bbb
279 ## END
280
281 #### command -p (hide tool in custom path)
282 mkdir -p $TMP/bin
283 echo "echo hello" > $TMP/bin/hello
284 chmod +x $TMP/bin/hello
285 export PATH=$TMP/bin
286 command -p hello
287 ## status: 127
288
289 #### command -p (find hidden tool in default path)
290 export PATH=''
291 command -p ls
292 ## status: 0
293
294
295 #### $(command type ls)
296 type() { echo FUNCTION; }
297 type
298 s=$(command type echo)
299 echo $s | grep builtin > /dev/null
300 echo status=$?
301 ## STDOUT:
302 FUNCTION
303 status=0
304 ## END
305 ## N-I zsh STDOUT:
306 FUNCTION
307 status=1
308 ## END
309 ## N-I mksh STDOUT:
310 status=1
311 ## END
312
313 #### builtin
314 cd () { echo "hi"; }
315 cd
316 builtin cd / && pwd
317 unset -f cd
318 ## STDOUT:
319 hi
320 /
321 ## END
322 ## N-I dash/ash STDOUT:
323 hi
324 ## END
325
326 #### builtin ls not found
327 builtin ls
328 ## status: 1
329 ## N-I dash/ash status: 127
330
331 #### builtin usage
332
333 builtin
334 echo status=$?
335
336 builtin --
337 echo status=$?
338
339 builtin -- false
340 echo status=$?
341
342 ## STDOUT:
343 status=0
344 status=0
345 status=1
346 ## END
347
348 ## BUG zsh STDOUT:
349 status=0
350 status=1
351 status=1
352 ## END
353
354 ## N-I dash/ash STDOUT:
355 status=127
356 status=127
357 status=127
358 ## END
359
360 #### builtin command echo hi
361 builtin command echo hi
362 ## status: 0
363 ## stdout: hi
364 ## N-I dash/ash status: 127
365 ## N-I dash/ash stdout-json: ""