Python 3.6 glob include hidden files and folders
Adding an answer for the bounty question; getting the result of hidden and non-hidden files in a single command.
As @reducidng activity mentioned, glob treats . files as a special use-case. To get both regular and hidden files in a single loop, we can use itertools.chain
with glob.iglob
iterators. for example,
→ ls -A
.chen file.text so1.py
>>> import glob, itertools
>>> for i in itertools.chain(glob.iglob('**'), glob.iglob('.**')):
... print(i)
...
file.text
so1.py
.chen
# If you want it as a variable, you can list() it.
>>> l = list(itertools.chain(glob.iglob('**'), glob.iglob('.**')))
>>> l
['file.text', 'so1.py', '.chen']
>>>
Note: it does not fully work (yet). Let's say you have .hello
, .dot/hello.txt
, .dot/.hello.txt
, nodot/hello.txt
, nodot/.hello.txt
. Then neither:
itertools.chain(glob.iglob('**', recursive=True), glob.iglob('.**', recursive=True))
nor
itertools.chain(glob.iglob('**/*', recursive=True), glob.iglob('.**/*', recursive=True))
give all files.
From https://docs.python.org/3/library/glob.html
Note that unlike fnmatch.fnmatch(), glob treats filenames beginning with a dot (.) as special cases
If the directory contains files starting with . they won’t be matched by default. For example, consider a directory containing card.gif and .card.gif:
import glob glob.glob('*.gif') # ['card.gif'] glob.glob('.c*') # ['.card.gif']
From what I see it requires two separate globs to get both hidden and not hidden ones, for example using https://stackoverflow.com/a/4829130/4130619.
I had this same issue and wished glob.glob had an optional parameter to include dot files. I wanted to be able to include ALL dot files in ALL directories including directories that start with dot. Its just not possible to do this with glob.glob. However I found that Python has pathlib standard module which has a glob function which operates differently, it will include dot files. The function operates a little differently, in particular it does not return a list of strings, but instead path objects. However I used the following
files=[]
file_refs = pathlib.Path(".").glob(pattern)
for file in file_refs:
files.append(str(file))
The other noticeable difference I found was a glob pattern ending with **. This returned nothing in the pathlib version but would return all the files in the glob.glob one. To get the same results I added a line to check if the pattern ended with ** and if so then append /* to it.
The following code is a replacement for your example that include the files in directories starting with dot
import pathlib
for fileref in pathlib.Path('/path/').glob('**/*.ext'):
filename = str(fileref)
print(filename)