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