| 1 | # |
| 2 | # NOTE: Could move spec/03-glob.sh here. |
| 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 | fun() { |
| 60 | echo $@ |
| 61 | } |
| 62 | fun '_tmp/*.B' |
| 63 | ## stdout: _tmp/b.B |
| 64 | |
| 65 | #### no glob after ~ expansion |
| 66 | HOME=* |
| 67 | echo ~/*.py |
| 68 | ## stdout: */*.py |
| 69 | |
| 70 | #### store literal globs in array then expand |
| 71 | touch _tmp/a.A _tmp/aa.A _tmp/b.B |
| 72 | g=("_tmp/*.A" "_tmp/*.B") |
| 73 | echo ${g[@]} |
| 74 | ## stdout: _tmp/a.A _tmp/aa.A _tmp/b.B |
| 75 | ## N-I dash/ash stdout-json: "" |
| 76 | ## N-I dash/ash status: 2 |
| 77 | |
| 78 | #### glob inside array |
| 79 | touch _tmp/a.A _tmp/aa.A _tmp/b.B |
| 80 | g=(_tmp/*.A _tmp/*.B) |
| 81 | echo "${g[@]}" |
| 82 | ## stdout: _tmp/a.A _tmp/aa.A _tmp/b.B |
| 83 | ## N-I dash/ash stdout-json: "" |
| 84 | ## N-I dash/ash status: 2 |
| 85 | |
| 86 | #### glob with escaped - in char class |
| 87 | touch _tmp/foo.- |
| 88 | touch _tmp/c.C |
| 89 | echo _tmp/*.[C-D] _tmp/*.[C\-D] |
| 90 | ## stdout: _tmp/c.C _tmp/c.C _tmp/foo.- |
| 91 | |
| 92 | #### glob with char class expression |
| 93 | # note: mksh doesn't support [[:punct:]] ? |
| 94 | touch _tmp/e.E _tmp/foo.- |
| 95 | echo _tmp/*.[[:punct:]E] |
| 96 | ## stdout: _tmp/e.E _tmp/foo.- |
| 97 | ## BUG mksh stdout: _tmp/*.[[:punct:]E] |
| 98 | |
| 99 | #### glob double quotes |
| 100 | # note: mksh doesn't support [[:punct:]] ? |
| 101 | touch _tmp/\"quoted.py\" |
| 102 | echo _tmp/\"*.py\" |
| 103 | ## stdout: _tmp/"quoted.py" |
| 104 | |
| 105 | #### glob escaped |
| 106 | # - mksh doesn't support [[:punct:]] ? |
| 107 | # - python shell fails because \[ not supported! |
| 108 | touch _tmp/\[abc\] _tmp/\? |
| 109 | echo _tmp/\[???\] _tmp/\? |
| 110 | ## stdout: _tmp/[abc] _tmp/? |
| 111 | |
| 112 | #### : escaped |
| 113 | touch _tmp/foo.- |
| 114 | echo _tmp/*.[[:punct:]] _tmp/*.[[:punct\:]] |
| 115 | ## stdout: _tmp/foo.- _tmp/*.[[:punct:]] |
| 116 | ## BUG mksh stdout: _tmp/*.[[:punct:]] _tmp/*.[[:punct:]] |
| 117 | ## BUG ash stdout: _tmp/foo.- _tmp/foo.- |
| 118 | |
| 119 | #### Redirect to glob, not evaluated |
| 120 | # This writes to *.F, not foo.F |
| 121 | rm _tmp/*.F |
| 122 | touch _tmp/f.F |
| 123 | echo foo > _tmp/*.F |
| 124 | cat '_tmp/*.F' |
| 125 | ## status: 0 |
| 126 | ## stdout: foo |
| 127 | ## BUG bash status: 1 |
| 128 | ## BUG bash stdout-json: "" |
| 129 | |
| 130 | #### Glob after var manipulation |
| 131 | touch _tmp/foo.zzz _tmp/bar.zzz |
| 132 | g='_tmp/*.zzzZ' |
| 133 | echo $g ${g%Z} |
| 134 | ## stdout: _tmp/*.zzzZ _tmp/bar.zzz _tmp/foo.zzz |
| 135 | |
| 136 | #### Glob after part joining |
| 137 | touch _tmp/foo.yyy _tmp/bar.yyy |
| 138 | g='_tmp/*.yy' |
| 139 | echo $g ${g}y |
| 140 | ## stdout: _tmp/*.yy _tmp/bar.yyy _tmp/foo.yyy |
| 141 | |
| 142 | #### Glob flags on file system |
| 143 | touch _tmp/-n _tmp/zzzzz |
| 144 | cd _tmp |
| 145 | echo -* hello zzzz? |
| 146 | ## stdout-json: "hello zzzzz" |
| 147 | |
| 148 | #### set -o noglob |
| 149 | cd $REPO_ROOT |
| 150 | touch _tmp/spec-tmp/a.zz _tmp/spec-tmp/b.zz |
| 151 | echo _tmp/spec-tmp/*.zz |
| 152 | set -o noglob |
| 153 | echo _tmp/spec-tmp/*.zz |
| 154 | ## stdout-json: "_tmp/spec-tmp/a.zz _tmp/spec-tmp/b.zz\n_tmp/spec-tmp/*.zz\n" |
| 155 | |
| 156 | #### set -o noglob (bug #698) |
| 157 | var='\z' |
| 158 | set -f |
| 159 | echo $var |
| 160 | ## STDOUT: |
| 161 | \z |
| 162 | ## END |
| 163 | |
| 164 | #### shopt -s nullglob |
| 165 | argv.py _tmp/spec-tmp/*.nonexistent |
| 166 | shopt -s nullglob |
| 167 | argv.py _tmp/spec-tmp/*.nonexistent |
| 168 | ## stdout-json: "['_tmp/spec-tmp/*.nonexistent']\n[]\n" |
| 169 | ## N-I dash/mksh/ash stdout-json: "['_tmp/spec-tmp/*.nonexistent']\n['_tmp/spec-tmp/*.nonexistent']\n" |
| 170 | |
| 171 | #### shopt -s failglob in command context |
| 172 | argv.py *.ZZ |
| 173 | shopt -s failglob |
| 174 | argv.py *.ZZ # nothing is printed, not [] |
| 175 | echo status=$? |
| 176 | ## STDOUT: |
| 177 | ['*.ZZ'] |
| 178 | status=1 |
| 179 | ## END |
| 180 | ## N-I dash/mksh/ash STDOUT: |
| 181 | ['*.ZZ'] |
| 182 | ['*.ZZ'] |
| 183 | status=0 |
| 184 | ## END |
| 185 | |
| 186 | #### shopt -s failglob in loop context |
| 187 | for x in *.ZZ; do echo $x; done |
| 188 | echo status=$? |
| 189 | shopt -s failglob |
| 190 | for x in *.ZZ; do echo $x; done |
| 191 | echo status=$? |
| 192 | ## STDOUT: |
| 193 | *.ZZ |
| 194 | status=0 |
| 195 | status=1 |
| 196 | ## END |
| 197 | ## N-I dash/mksh/ash STDOUT: |
| 198 | *.ZZ |
| 199 | status=0 |
| 200 | *.ZZ |
| 201 | status=0 |
| 202 | ## END |
| 203 | |
| 204 | #### Don't glob flags on file system with GLOBIGNORE |
| 205 | # This is a bash-specific extension. |
| 206 | expr $0 : '.*/osh$' >/dev/null && exit 99 # disabled until cd implemented |
| 207 | touch _tmp/-n _tmp/zzzzz |
| 208 | cd _tmp # this fail in osh |
| 209 | GLOBIGNORE=-*:zzzzz # colon-separated pattern list |
| 210 | echo -* hello zzzz? |
| 211 | ## stdout-json: "-* hello zzzz?\n" |
| 212 | ## N-I dash/mksh/ash stdout-json: "hello zzzzz" |
| 213 | ## status: 0 |
| 214 | |
| 215 | #### Splitting/Globbing doesn't happen on local assignment |
| 216 | cd $REPO_ROOT |
| 217 | |
| 218 | f() { |
| 219 | # Dash splits words and globs before handing it to the 'local' builtin. But |
| 220 | # ash doesn't! |
| 221 | local foo=$1 |
| 222 | echo "$foo" |
| 223 | } |
| 224 | f 'void *' |
| 225 | ## stdout: void * |
| 226 | ## BUG dash stdout-json: "" |
| 227 | ## BUG dash status: 2 |
| 228 | |
| 229 | #### Glob of unescaped [[] and []] |
| 230 | touch $TMP/[ $TMP/] |
| 231 | cd $TMP |
| 232 | echo [\[z] [\]z] # the right way to do it |
| 233 | echo [[z] []z] # also accepted |
| 234 | ## STDOUT: |
| 235 | [ ] |
| 236 | [ ] |
| 237 | ## END |
| 238 | |
| 239 | #### Glob of negated unescaped [[] and []] |
| 240 | # osh does this "correctly" because it defers to libc! |
| 241 | touch $TMP/_G |
| 242 | cd $TMP |
| 243 | echo _[^\[z] _[^\]z] # the right way to do it |
| 244 | echo _[^[z] _[^]z] # also accepted |
| 245 | ## STDOUT: |
| 246 | _G _G |
| 247 | _G _G |
| 248 | ## END |
| 249 | ## BUG dash/mksh STDOUT: |
| 250 | _[^[z] _[^]z] |
| 251 | _[^[z] _[^]z] |
| 252 | ## END |
| 253 | |
| 254 | #### PatSub of unescaped [[] and []] |
| 255 | x='[foo]' |
| 256 | echo ${x//[\[z]/<} # the right way to do it |
| 257 | echo ${x//[\]z]/>} |
| 258 | echo ${x//[[z]/<} # also accepted |
| 259 | echo ${x//[]z]/>} |
| 260 | ## STDOUT: |
| 261 | <foo] |
| 262 | [foo> |
| 263 | <foo] |
| 264 | [foo> |
| 265 | ## END |
| 266 | ## N-I dash stdout-json: "" |
| 267 | ## N-I dash status: 2 |
| 268 | |
| 269 | #### PatSub of negated unescaped [[] and []] |
| 270 | x='[foo]' |
| 271 | echo ${x//[^\[z]/<} # the right way to do it |
| 272 | echo ${x//[^\]z]/>} |
| 273 | echo ${x//[^[z]/<} # also accepted |
| 274 | #echo ${x//[^]z]/>} # only busybox ash interprets as ^\] |
| 275 | ## STDOUT: |
| 276 | [<<<< |
| 277 | >>>>] |
| 278 | [<<<< |
| 279 | ## END |
| 280 | # mksh is doing something very odd, ignoring ^ altogether? |
| 281 | ## BUG mksh STDOUT: |
| 282 | <foo] |
| 283 | [foo> |
| 284 | <foo] |
| 285 | ## END |
| 286 | ## N-I dash stdout-json: "" |
| 287 | ## N-I dash status: 2 |
| 288 | |
| 289 | #### Glob unicode char |
| 290 | |
| 291 | touch $TMP/__a__ |
| 292 | touch $TMP/__μ__ |
| 293 | cd $TMP |
| 294 | |
| 295 | echo __?__ |
| 296 | |
| 297 | ## STDOUT: |
| 298 | __a__ __μ__ |
| 299 | ## END |
| 300 | ## BUG dash/mksh/ash STDOUT: |
| 301 | __a__ |
| 302 | ## END |
| 303 | # note: zsh also passes this, but it doesn't run with this file. |
| 304 | |
| 305 | #### dotglob (bash option that dashglob is roughly consistent with) |
| 306 | mkdir -p $TMP/dotglob |
| 307 | cd $TMP/dotglob |
| 308 | touch .foorc other |
| 309 | |
| 310 | echo * |
| 311 | shopt -s dotglob |
| 312 | echo * |
| 313 | ## STDOUT: |
| 314 | other |
| 315 | .foorc other |
| 316 | ## END |
| 317 | ## N-I dash/mksh/ash STDOUT: |
| 318 | other |
| 319 | other |
| 320 | ## END |
| 321 |