How does GLOBIGNORE work?
Solution 1
The filenames
.
and..
are always ignored whenGLOBIGNORE
is set and not null.
Most of the time, it is not desirable to include .
and ..
as wildcard matches, since they don't represent files inside the directory — they're hacks to make directory navigation work. In fact, the origin of dot files is a bug in an early version of the ls
command. The author meant to exclude .
and ..
from the listing but accidentally excluded all files that begin with .
. Thus dot files became hidden from ls
. Shells followed suit by hiding dot files like ls
. However the way this was done was again a hack: files beginning with .
are only excluded if the dot isn't matched explicitly in the pattern. So the pattern .*
includes .
and ..
.
To preserve compatibility with existing scripts, modern shells still include .
and ..
(except zsh, which on this issue like many others has a saner but not backward compatible behavior). However, if you set GLOBIGNORE
, you are using a bash-specific feature, which shows that you aren't interested in backward compatibility. So pattern matching changes to exclude .
and ..
from all pattern matches.
Setting GLOBIGNORE=.
excludes a file that is excluded automatically anyway whenever GLOBIGNORE
is set, so it is equivalent to shopt -s dotglob
except that .
and ..
are furthermore excluded from all patterns.
Solution 2
From the section entitled "Pathname Expansion" in man bash
:
The file names ''.'' and ''..'' are always ignored when GLOBIGNORE is set and not null.
Related videos on Youtube
Ernest A
Updated on September 18, 2022Comments
-
Ernest A almost 2 years
According to bash's manual page:
GLOBIGNORE A colon-separated list of patterns defining the set of filenames to be ignored by pathname expansion. If a filename matched by a pathname expansion pattern also matches one of the patterns in GLOBIGNORE, it is removed from the list of matches.
However in practice...
$ bash --noprofile --norc bash-4.2$ touch .bar bash-4.2$ echo .* . .. .bar bash-4.2$ GLOBIGNORE=. bash-4.2$ echo .* .bar
Why is
..
removed from the list of matches? As far as I know, the pattern.
does NOT match..
, does it? -
Stéphane Chazelas over 8 yearsActually, no,
GLOBIGNORE='?(*/)@(.|..)'
would fail to exclude.
and..
in.*/foo
.GLOBIGNORE='?(*/)@(.|..)?(/*)'
would break globs like./*
...