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