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