1 ## oils_failures_allowed: 0
2 ## compare_shells: bash
3 ## legacy_tmp_dir: true
4
5 #### Don't glob flags on file system with GLOBIGNORE
6 touch _tmp/-n _tmp/zzzzz
7 cd _tmp # this fail in osh
8 GLOBIGNORE=-*:zzzzz # colon-separated pattern list
9 echo -* hello zzzz?
10 ## STDOUT:
11 -* hello zzzz?
12 ## END
13 ## N-I dash/mksh/ash stdout-json: "hello zzzzz"
14 ## status: 0
15
16 #### basic star case -> ignore files with txt extension
17 touch {basic.md,basic.txt}
18 GLOBIGNORE=*.txt
19 echo *.*
20 ## STDOUT:
21 basic.md
22 ## END
23
24 #### basic question mark case -> ignore txt files with one char filename
25 touch {1.txt,10.txt}
26 GLOBIGNORE=?.txt
27 echo *.*
28 ## STDOUT:
29 10.txt
30 ## END
31
32 #### multiple patterns -> ignore files with o or h extensions
33 touch {hello.c,hello.h,hello.o,hello}
34 GLOBIGNORE=*.o:*.h
35 echo hello*
36 ## STDOUT:
37 hello hello.c
38 ## END
39
40 #### ignore specific file
41 mkdir src
42 touch src/{__init__.py,__main__.py}
43 GLOBIGNORE='src/__init__.py'
44 echo src/*
45 ## STDOUT:
46 src/__main__.py
47 ## END
48
49 #### ignore contents of specific directories
50 mkdir {src,compose,dist,node_modules}
51 touch src/{a.js,b.js}
52 touch compose/{base.compose.yaml,dev.compose.yaml}
53 touch dist/index.js
54 touch node_modules/package.js
55 GLOBIGNORE=dist/*:node_modules/*
56 echo */*
57 ## STDOUT:
58 compose/base.compose.yaml compose/dev.compose.yaml src/a.js src/b.js
59 ## END
60
61 #### find files in subdirectory but not the ignored pattern
62 mkdir {dir1,dir2}
63 touch dir1/{a.txt,ignore.txt}
64 touch dir2/{a.txt,ignore.txt}
65 GLOBIGNORE=*/ignore*
66 echo */*
67 ## STDOUT:
68 dir1/a.txt dir2/a.txt
69 ## END
70
71 #### basic range cases
72 rm -rf _tmp
73 touch {a,b,c,d,A,B,C,D}
74 GLOBIGNORE=*[ab]*
75 echo *
76 GLOBIGNORE=*[ABC]*
77 echo *
78 GLOBIGNORE=*[!ab]*
79 echo *
80 ## STDOUT:
81 A B C D c d
82 D a b c d
83 a b
84 ## END
85
86 #### range cases using character classes
87 touch {_testing.py,pyproject.toml,20231114.log,.env}
88 touch 'has space.docx'
89 GLOBIGNORE=[[:alnum:]]*
90 echo *.*
91 GLOBIGNORE=[![:alnum:]]*
92 echo *.*
93 GLOBIGNORE=*[[:space:]]*
94 echo *.*
95 GLOBIGNORE=[[:digit:]_.]*
96 echo *.*
97 ## STDOUT:
98 .env _testing.py
99 20231114.log has space.docx pyproject.toml
100 .env 20231114.log _testing.py pyproject.toml
101 has space.docx pyproject.toml
102 ## END
103
104 #### ignore everything
105 # This pattern appears in public repositories
106 touch {1.txt,2.log,3.md}
107 GLOBIGNORE=*
108 echo *
109 ## STDOUT:
110 *
111 ## END
112
113 #### treat escaped patterns literally
114 touch {escape-10.txt,escape*.txt}
115 GLOBIGNORE="escape\*.txt"
116 echo *.*
117 ## STDOUT:
118 escape-10.txt
119 ## END
120
121 #### resetting globignore reverts to default behaviour
122 touch reset.txt
123 GLOBIGNORE=*.txt
124 echo *.*
125 GLOBIGNORE=
126 echo *.*
127 ## STDOUT:
128 *.*
129 reset.txt
130 ## END
131
132 #### find dotfiles while ignoring . or ..
133 # globskipdots is enabled by default in bash >=5.2
134 # for bash <5.2 this pattern is a common way to match dotfiles but not . or ..
135 shopt -u globskipdots
136 touch .env
137 GLOBIGNORE=.:..
138 echo .*
139 GLOBIGNORE=
140 echo .* | sort
141 ## STDOUT:
142 .env
143 . .. .env
144 ## END
145
146 #### different styles
147 # each style of "ignore everything" spotted in a public repo
148 touch image.jpeg
149 GLOBIGNORE=*
150 echo *
151 GLOBIGNORE='*'
152 echo *
153 GLOBIGNORE="*"
154 echo *
155 GLOBIGNORE=\*
156 echo *
157 ## STDOUT:
158 *
159 *
160 *
161 *
162 ## END
163
164 #### . and .. always filtered when GLOBIGNORE is set
165 # When GLOBIGNORE is set to any non-null value, . and .. are always filtered
166 touch .hidden
167 GLOBIGNORE=*.txt
168
169 echo .*
170 shopt -u globskipdots
171 echo .*
172
173 ## STDOUT:
174 .hidden
175 .hidden
176 ## END
177
178 #### When GLOBIGNORE is set, glob may become empty (nullglob too)
179 touch -- foo.txt -foo.txt
180
181 echo *t
182
183 GLOBIGNORE=*.txt
184 echo *t
185
186 shopt -s nullglob
187 echo nullglob *t
188
189 ## STDOUT:
190 -foo.txt foo.txt
191 *t
192 nullglob
193 ## END
194
195 #### When GLOBIGNORE is set, no_dash_glob isn't respected
196 case $SH in bash) exit ;; esac
197
198 touch -- foo.txt -foo.txt
199
200 shopt -s no_dash_glob # YSH option
201
202 echo * # expansion does NOT include -foo.txt
203
204 GLOBIGNORE=f*.txt
205 echo * # expansion includes -foo.txt, because it doesn't match GLOBIGNORE
206
207 ## STDOUT:
208 _tmp foo.txt
209 -foo.txt _tmp
210 ## END
211 ## N-I bash STDOUT:
212 ## END
213
214 #### Extended glob expansion combined with GLOBIGNORE
215 shopt -s extglob
216
217 touch foo.cc foo.h bar.cc bar.h
218 echo @(*.cc|*.h)
219 GLOBIGNORE=foo.*
220 echo @(*.cc|*.h)
221
222 ## STDOUT:
223 bar.cc bar.h foo.cc foo.h
224 bar.cc bar.h
225 ## END