如何使用glob读取有限的数字文件名集?

16 投票
3 回答
20180 浏览
提问于 2025-04-18 06:58

如何使用glob只读取有限数量的文件?

我有一些json文件,文件名是从50到20000的数字(比如50.json、51.json、52.json……一直到19999.json和20000.json),它们都在同一个文件夹里。我想只读取编号在15000到18000之间的文件。

为此,我正在使用glob,下面是我的代码,但每次我尝试过滤这些数字时,它都会生成一个空列表。我已经尽力按照这个链接的说明去做(https://docs.python.org/2/library/glob.html),但我不太确定哪里出了问题。

>>> directory = "/Users/Chris/Dropbox"
>>> read_files = glob.glob(directory+"/[15000-18000].*")
>>> print read_files
[]

另外,如果我想要读取任何大于18000的文件呢?

3 个回答

0

我修改了@martineau的代码,因为我在使用我的文件时遇到了一个错误,正则表达式返回了一个空数组(可能是因为我在用Python 3?)。我还把输出改成用空格分隔,这样可以在Linux命令行中使用,比如:

cp `python readfiles.py` mydir

反引号会执行里面的命令,并把输出插入到命令行中。这假设返回的文件名中没有空格。

这是修改后的代码:

Import os, re
directory = "."
all_files = os.listdir(directory)

read_files = [this_file for this_file in all_files 
    if re.search(r'\d+', this_file) and int(re.findall(r'\d+', this_file)[-1]) > 18000
]

print(' '.join(read_files))
5

虽然这段代码可能不算特别优雅,但你可以按照下面的方式自己实现过滤功能:

import os, re
directory = "/Users/Chris/Dropbox"
all_files = os.listdir(directory)

read_files = [this_file for this_file in all_files 
                if (int(re.findall('\d+', this_file)[-1]) > 18000)]

print read_files

这里最关键的一行是(for this_file in all_files),它会遍历目录中的每个文件名,然后提取出文件名中的数字部分(re.findall('\d+', this_file))。如果这些数字中的最后一个数字(转换为整数后)大于18000,就会把这个文件名加入到read_files中。

我觉得如果文件名中没有数字,这段代码可能会出问题,所以使用时要小心。


补充:我看到之前的回答已经被修改,加入了一种看起来更合理的做法。

23

你在使用通配符语法的时候搞错了;[..]这个部分是按每个字符来处理的。下面这个通配符可以正确匹配你的文件:

'1[5-8][0-9][0-9][0-9].*'

其实,glob这个工具在后台使用的是fnmatch,它会把你的模式转换成正则表达式。你的模式转换成了:

>>> import fnmatch
>>> fnmatch.translate('[15000-18000].*')
'[15000-18000]\\..*\\Z(?ms)'

这个表达式会匹配一个字符在.之前,后面跟着015或者8。其他的都不行。

glob的模式功能比较有限;用它来匹配数字范围并不简单;你需要为每个范围创建单独的通配符,比如说(glob('1[8-9][0-9][0-9][0-9]') + glob('2[0-9][0-9][0-9][0-9]'),等等)。

不如自己来过滤一下:

directory = "/Users/Chris/Dropbox"

for filename in os.listdir(directory):
    basename, ext = os.path.splitext(filename)
    if ext != '.json':
        continue
    try:
        number = int(basename)
    except ValueError:
        continue  # not numeric
    if 18000 <= number <= 19000:
        # process file
        filename = os.path.join(directory, filename)

撰写回答