1 | ## oils_failures_allowed: 3
|
2 | ## compare_shells: bash dash mksh ash
|
3 |
|
4 | #### glob double quote escape
|
5 | echo "*.sh"
|
6 | ## stdout: *.sh
|
7 |
|
8 | #### glob single quote escape
|
9 | echo "*.sh"
|
10 | ## stdout: *.sh
|
11 |
|
12 | #### glob backslash escape
|
13 | echo \*.sh
|
14 | ## stdout: *.sh
|
15 |
|
16 | #### 1 char glob
|
17 | cd $REPO_ROOT
|
18 | echo [b]in
|
19 | ## stdout: bin
|
20 |
|
21 | #### 0 char glob -- does NOT work
|
22 | echo []bin
|
23 | ## stdout: []bin
|
24 |
|
25 | #### looks like glob at the start, but isn't
|
26 | echo [bin
|
27 | ## stdout: [bin
|
28 |
|
29 | #### looks like glob plus negation at the start, but isn't
|
30 | echo [!bin
|
31 | ## stdout: [!bin
|
32 |
|
33 | #### glob can expand to command and arg
|
34 | cd $REPO_ROOT
|
35 | spec/testdata/echo.s[hz]
|
36 | ## stdout: spec/testdata/echo.sz
|
37 |
|
38 | #### glob after var expansion
|
39 | touch _tmp/a.A _tmp/aa.A _tmp/b.B
|
40 | f="_tmp/*.A"
|
41 | g="$f _tmp/*.B"
|
42 | echo $g
|
43 | ## stdout: _tmp/a.A _tmp/aa.A _tmp/b.B
|
44 |
|
45 | #### quoted var expansion with glob meta characters
|
46 | touch _tmp/a.A _tmp/aa.A _tmp/b.B
|
47 | f="_tmp/*.A"
|
48 | echo "[ $f ]"
|
49 | ## stdout: [ _tmp/*.A ]
|
50 |
|
51 | #### glob after "$@" expansion
|
52 | fun() {
|
53 | echo "$@"
|
54 | }
|
55 | fun '_tmp/*.B'
|
56 | ## stdout: _tmp/*.B
|
57 |
|
58 | #### glob after $@ expansion
|
59 | touch _tmp/b.B
|
60 | fun() {
|
61 | echo $@
|
62 | }
|
63 | fun '_tmp/*.B'
|
64 | ## stdout: _tmp/b.B
|
65 |
|
66 | #### no glob after ~ expansion
|
67 | HOME=*
|
68 | echo ~/*.py
|
69 | ## stdout: */*.py
|
70 |
|
71 | #### store literal globs in array then expand
|
72 | touch _tmp/a.A _tmp/aa.A _tmp/b.B
|
73 | g=("_tmp/*.A" "_tmp/*.B")
|
74 | echo ${g[@]}
|
75 | ## stdout: _tmp/a.A _tmp/aa.A _tmp/b.B
|
76 | ## N-I dash/ash stdout-json: ""
|
77 | ## N-I dash/ash status: 2
|
78 |
|
79 | #### glob inside array
|
80 | touch _tmp/a.A _tmp/aa.A _tmp/b.B
|
81 | g=(_tmp/*.A _tmp/*.B)
|
82 | echo "${g[@]}"
|
83 | ## stdout: _tmp/a.A _tmp/aa.A _tmp/b.B
|
84 | ## N-I dash/ash stdout-json: ""
|
85 | ## N-I dash/ash status: 2
|
86 |
|
87 | #### glob with escaped - in char class
|
88 | touch _tmp/foo.-
|
89 | touch _tmp/c.C
|
90 | echo _tmp/*.[C-D] _tmp/*.[C\-D]
|
91 | ## stdout: _tmp/c.C _tmp/c.C _tmp/foo.-
|
92 |
|
93 | #### glob with char class expression
|
94 | # note: mksh doesn't support [[:punct:]] ?
|
95 | touch _tmp/e.E _tmp/foo.-
|
96 | echo _tmp/*.[[:punct:]E]
|
97 | ## stdout: _tmp/e.E _tmp/foo.-
|
98 | ## BUG mksh stdout: _tmp/*.[[:punct:]E]
|
99 |
|
100 | #### glob double quotes
|
101 | # note: mksh doesn't support [[:punct:]] ?
|
102 | touch _tmp/\"quoted.py\"
|
103 | echo _tmp/\"*.py\"
|
104 | ## stdout: _tmp/"quoted.py"
|
105 |
|
106 | #### glob escaped
|
107 | # - mksh doesn't support [[:punct:]] ?
|
108 | # - python shell fails because \[ not supported!
|
109 | touch _tmp/\[abc\] _tmp/\?
|
110 | echo _tmp/\[???\] _tmp/\?
|
111 | ## stdout: _tmp/[abc] _tmp/?
|
112 |
|
113 | #### : escaped
|
114 | touch _tmp/foo.-
|
115 | echo _tmp/*.[[:punct:]] _tmp/*.[[:punct\:]]
|
116 | ## stdout: _tmp/foo.- _tmp/*.[[:punct:]]
|
117 | ## BUG mksh stdout: _tmp/*.[[:punct:]] _tmp/*.[[:punct:]]
|
118 | ## BUG ash stdout: _tmp/foo.- _tmp/foo.-
|
119 |
|
120 | #### Glob after var manipulation
|
121 | touch _tmp/foo.zzz _tmp/bar.zzz
|
122 | g='_tmp/*.zzzZ'
|
123 | echo $g ${g%Z}
|
124 | ## stdout: _tmp/*.zzzZ _tmp/bar.zzz _tmp/foo.zzz
|
125 |
|
126 | #### Glob after part joining
|
127 | touch _tmp/foo.yyy _tmp/bar.yyy
|
128 | g='_tmp/*.yy'
|
129 | echo $g ${g}y
|
130 | ## stdout: _tmp/*.yy _tmp/bar.yyy _tmp/foo.yyy
|
131 |
|
132 | #### Glob flags on file system
|
133 | touch _tmp/-n _tmp/zzzzz
|
134 | cd _tmp
|
135 | echo -* hello zzzz?
|
136 | ## stdout-json: "hello zzzzz"
|
137 |
|
138 | #### set -o noglob
|
139 | cd $REPO_ROOT
|
140 | touch _tmp/spec-tmp/a.zz _tmp/spec-tmp/b.zz
|
141 | echo _tmp/spec-tmp/*.zz
|
142 | set -o noglob
|
143 | echo _tmp/spec-tmp/*.zz
|
144 | ## stdout-json: "_tmp/spec-tmp/a.zz _tmp/spec-tmp/b.zz\n_tmp/spec-tmp/*.zz\n"
|
145 |
|
146 | #### set -o noglob (bug #698)
|
147 | var='\z'
|
148 | set -f
|
149 | echo $var
|
150 | ## STDOUT:
|
151 | \z
|
152 | ## END
|
153 |
|
154 | #### shopt -s nullglob
|
155 | argv.py _tmp/spec-tmp/*.nonexistent
|
156 | shopt -s nullglob
|
157 | argv.py _tmp/spec-tmp/*.nonexistent
|
158 | ## stdout-json: "['_tmp/spec-tmp/*.nonexistent']\n[]\n"
|
159 | ## N-I dash/mksh/ash stdout-json: "['_tmp/spec-tmp/*.nonexistent']\n['_tmp/spec-tmp/*.nonexistent']\n"
|
160 |
|
161 | #### shopt -s failglob in command context
|
162 | argv.py *.ZZ
|
163 | shopt -s failglob
|
164 | argv.py *.ZZ # nothing is printed, not []
|
165 | echo status=$?
|
166 | ## STDOUT:
|
167 | ['*.ZZ']
|
168 | status=1
|
169 | ## END
|
170 | ## N-I dash/mksh/ash STDOUT:
|
171 | ['*.ZZ']
|
172 | ['*.ZZ']
|
173 | status=0
|
174 | ## END
|
175 |
|
176 | #### shopt -s failglob in loop context
|
177 | for x in *.ZZ; do echo $x; done
|
178 | echo status=$?
|
179 | shopt -s failglob
|
180 | for x in *.ZZ; do echo $x; done
|
181 | echo status=$?
|
182 | ## STDOUT:
|
183 | *.ZZ
|
184 | status=0
|
185 | status=1
|
186 | ## END
|
187 | ## N-I dash/mksh/ash STDOUT:
|
188 | *.ZZ
|
189 | status=0
|
190 | *.ZZ
|
191 | status=0
|
192 | ## END
|
193 |
|
194 | #### shopt -s failglob in array literal context
|
195 | myarr=(*.ZZ)
|
196 | echo "${myarr[@]}"
|
197 | shopt -s failglob
|
198 | myarr=(*.ZZ)
|
199 | echo status=$?
|
200 | ## STDOUT:
|
201 | *.ZZ
|
202 | status=1
|
203 | ## END
|
204 | ## N-I mksh STDOUT:
|
205 | *.ZZ
|
206 | status=0
|
207 | ## END
|
208 | ## N-I dash/ash stdout-json: ""
|
209 | ## N-I dash/ash status: 2
|
210 |
|
211 | #### shopt -s failglob exits properly in command context with set -e
|
212 | set -e
|
213 | argv.py *.ZZ
|
214 | shopt -s failglob
|
215 | argv.py *.ZZ
|
216 | echo status=$?
|
217 | ## STDOUT:
|
218 | ['*.ZZ']
|
219 | ## END
|
220 | ## status: 1
|
221 | ## N-I dash/mksh/ash STDOUT:
|
222 | ['*.ZZ']
|
223 | ## END
|
224 | ## N-I dash/mksh/ash status: 127
|
225 |
|
226 | #### shopt -s failglob exits properly in loop context with set -e
|
227 | set -e
|
228 | for x in *.ZZ; do echo $x; done
|
229 | echo status=$?
|
230 |
|
231 | shopt -s failglob
|
232 | for x in *.ZZ; do echo $x; done
|
233 | echo status=$?
|
234 |
|
235 | ## status: 1
|
236 | ## STDOUT:
|
237 | *.ZZ
|
238 | status=0
|
239 | ## END
|
240 |
|
241 | ## N-I dash/mksh/ash status: 127
|
242 | ## N-I dash/mksh/ash STDOUT:
|
243 | *.ZZ
|
244 | status=0
|
245 | ## END
|
246 |
|
247 | #### shopt -s failglob behavior on single line with semicolon
|
248 | # bash behaves differently when commands are separated by a semicolon than when
|
249 | # separated by a newline. This behavior doesn't make sense or seem to be
|
250 | # intentional, so osh does not mimic it.
|
251 |
|
252 | shopt -s failglob
|
253 | echo *.ZZ; echo status=$? # bash doesn't execute the second part!
|
254 | echo *.ZZ
|
255 | echo status=$? # bash executes this
|
256 |
|
257 | ## STDOUT:
|
258 | status=1
|
259 | ## END
|
260 |
|
261 | ## OK osh STDOUT:
|
262 | status=1
|
263 | status=1
|
264 | ## END
|
265 |
|
266 | ## N-I dash/mksh/ash STDOUT:
|
267 | *.ZZ
|
268 | status=0
|
269 | *.ZZ
|
270 | status=0
|
271 | ## END
|
272 |
|
273 | #### Splitting/Globbing doesn't happen on local assignment
|
274 | cd $REPO_ROOT
|
275 |
|
276 | f() {
|
277 | # Dash splits words and globs before handing it to the 'local' builtin. But
|
278 | # ash doesn't!
|
279 | local foo=$1
|
280 | echo "$foo"
|
281 | }
|
282 | f 'void *'
|
283 | ## stdout: void *
|
284 | ## BUG dash stdout-json: ""
|
285 | ## BUG dash status: 2
|
286 |
|
287 | #### Glob of unescaped [[] and []]
|
288 | touch $TMP/[ $TMP/]
|
289 | cd $TMP
|
290 | echo [\[z] [\]z] # the right way to do it
|
291 | echo [[z] []z] # also accepted
|
292 | ## STDOUT:
|
293 | [ ]
|
294 | [ ]
|
295 | ## END
|
296 |
|
297 | #### Glob of negated unescaped [[] and []]
|
298 | # osh does this "correctly" because it defers to libc!
|
299 | touch $TMP/_G
|
300 | cd $TMP
|
301 | echo _[^\[z] _[^\]z] # the right way to do it
|
302 | echo _[^[z] _[^]z] # also accepted
|
303 | ## STDOUT:
|
304 | _G _G
|
305 | _G _G
|
306 | ## END
|
307 | ## BUG dash/mksh STDOUT:
|
308 | _[^[z] _[^]z]
|
309 | _[^[z] _[^]z]
|
310 | ## END
|
311 |
|
312 | #### PatSub of unescaped [[] and []]
|
313 | x='[foo]'
|
314 | echo ${x//[\[z]/<} # the right way to do it
|
315 | echo ${x//[\]z]/>}
|
316 | echo ${x//[[z]/<} # also accepted
|
317 | echo ${x//[]z]/>}
|
318 | ## STDOUT:
|
319 | <foo]
|
320 | [foo>
|
321 | <foo]
|
322 | [foo>
|
323 | ## END
|
324 | ## N-I dash stdout-json: ""
|
325 | ## N-I dash status: 2
|
326 |
|
327 | #### PatSub of negated unescaped [[] and []]
|
328 | x='[foo]'
|
329 | echo ${x//[^\[z]/<} # the right way to do it
|
330 | echo ${x//[^\]z]/>}
|
331 | echo ${x//[^[z]/<} # also accepted
|
332 | #echo ${x//[^]z]/>} # only busybox ash interprets as ^\]
|
333 | ## STDOUT:
|
334 | [<<<<
|
335 | >>>>]
|
336 | [<<<<
|
337 | ## END
|
338 | # mksh is doing something very odd, ignoring ^ altogether?
|
339 | ## BUG mksh STDOUT:
|
340 | <foo]
|
341 | [foo>
|
342 | <foo]
|
343 | ## END
|
344 | ## N-I dash stdout-json: ""
|
345 | ## N-I dash status: 2
|
346 |
|
347 | #### Glob unicode char
|
348 |
|
349 | touch $TMP/__a__
|
350 | touch $TMP/__μ__
|
351 | cd $TMP
|
352 |
|
353 | echo __?__
|
354 |
|
355 | ## STDOUT:
|
356 | __a__ __μ__
|
357 | ## END
|
358 | ## BUG dash/mksh/ash STDOUT:
|
359 | __a__
|
360 | ## END
|
361 | # note: zsh also passes this, but it doesn't run with this file.
|
362 |
|
363 | #### dotglob (bash option that dashglob is roughly consistent with)
|
364 | mkdir -p $TMP/dotglob
|
365 | cd $TMP/dotglob
|
366 | touch .foorc other
|
367 |
|
368 | echo *
|
369 | shopt -s dotglob
|
370 | echo *
|
371 | ## STDOUT:
|
372 | other
|
373 | .foorc other
|
374 | ## END
|
375 | ## N-I dash/mksh/ash STDOUT:
|
376 | other
|
377 | other
|
378 | ## END
|