获取目录中经过筛选的文件列表

我试图使用Python获取目录中的文件列表,但我不想要所有文件的列表。

我本质上想要的是做以下事情的能力,但使用Python而不执行ls。

ls 145592*.jpg

如果没有内置方法,我目前正在考虑编写一个for循环来遍历os.listdir()的结果,并将所有匹配的文件附加到一个新列表中。

但是,该目录中有很多文件,因此我希望有一个更有效的方法(或内置方法)。

530909 次浏览
import glob


jpgFilenamesList = glob.glob('145592*.jpg')

参见python文档中的glob

glob.glob()绝对是这样做的方式(根据Ignacio)。然而,如果你确实需要更复杂的匹配,你可以用一个列表推导式和re.match()来做,就像这样:

files = [f for f in os.listdir('.') if re.match(r'[0-9]+.*\.jpg', f)]

更灵活了,但正如你所说,效率降低了。

使用操作系统。遍历递归列出您的文件

import os
root = "/home"
pattern = "145992"
alist_filter = ['jpg','bmp','png','gif']
path=os.path.join(root,"mydir_to_scan")
for r,d,f in os.walk(path):
for file in f:
if file[-3:] in alist_filter and pattern in file:
print os.path.join(root,file)

保持简单:

import os
relevant_path = "[path to folder]"
included_extensions = ['jpg','jpeg', 'bmp', 'png', 'gif']
file_names = [fn for fn in os.listdir(relevant_path)
if any(fn.endswith(ext) for ext in included_extensions)]

我更喜欢这种形式的列表推导式,因为它的英文可读性很好。

我把第四行读成: 对于os中的每一个fn。

. Listdir为我的路径,只给我匹配任何一个包含的扩展名

对于python程序员新手来说,可能很难真正习惯使用列表推导式进行过滤,而且对于非常大的数据集可能会有一些内存开销,但对于列出目录和其他简单的字符串过滤任务,列表推导式会带来更干净的可记录的代码。

关于这种设计的唯一问题是,它不能防止您犯传递字符串而不是列表的错误。例如,如果您意外地将一个字符串转换为一个列表,并最终检查字符串的所有字符,您可能最终会得到大量的假阳性结果。

但有一个容易解决的问题总比有一个难以理解的解决方案要好。

你可能也喜欢更高级的方法(我已经实现并打包为findtools):

from findtools.find_files import (find_files, Match)




# Recursively find all *.txt files in **/home/**
txt_files_pattern = Match(filetype='f', name='*.txt')
found_files = find_files(path='/home', match=txt_files_pattern)


for found_file in found_files:
print found_file

可与

pip install findtools

另一个选择:

>>> import os, fnmatch
>>> fnmatch.filter(os.listdir('.'), '*.py')
['manage.py']

https://docs.python.org/3/library/fnmatch.html

你可以使用subprocess. check_output()作为

import subprocess


list_files = subprocess.check_output("ls 145992*.jpg", shell=True)

当然,引号之间的字符串可以是您希望在shell中执行并存储输出的任何内容。

初步的代码

import glob
import fnmatch
import pathlib
import os


pattern = '*.py'
path = '.'

解决方案1 -使用“glob”

# lookup in current dir
glob.glob(pattern)


In [2]: glob.glob(pattern)
Out[2]: ['wsgi.py', 'manage.py', 'tasks.py']

解决方案2 -使用“os”+“fnmatch”

版本2.1查找当前目录

# lookup in current dir
fnmatch.filter(os.listdir(path), pattern)


In [3]: fnmatch.filter(os.listdir(path), pattern)
Out[3]: ['wsgi.py', 'manage.py', 'tasks.py']

版本2.2查找递归

# lookup recursive
for dirpath, dirnames, filenames in os.walk(path):


if not filenames:
continue


pythonic_files = fnmatch.filter(filenames, pattern)
if pythonic_files:
for file in pythonic_files:
print('{}/{}'.format(dirpath, file))

结果

./wsgi.py
./manage.py
./tasks.py
./temp/temp.py
./apps/diaries/urls.py
./apps/diaries/signals.py
./apps/diaries/actions.py
./apps/diaries/querysets.py
./apps/library/tests/test_forms.py
./apps/library/migrations/0001_initial.py
./apps/polls/views.py
./apps/polls/formsets.py
./apps/polls/reports.py
./apps/polls/admin.py

解决方案3 -使用“pathlib”

# lookup in current dir
path_ = pathlib.Path('.')
tuple(path_.glob(pattern))


# lookup recursive
tuple(path_.rglob(pattern))

注:

  1. 在Python 3.4上测试
  2. 模块“pathlib”只在Python 3.4中添加
  3. Python 3.5使用glob.glob添加了递归查找的特性 https://docs.python.org/3.5/library/glob.html#glob.glob。因为我的机器安装了Python 3.4,所以我还没有测试过
import os


dir="/path/to/dir"
[x[0]+"/"+f for x in os.walk(dir) for f in x[2] if f.endswith(".jpg")]

这将为您提供一个包含完整路径的jpg文件列表。你可以用f替换x[0]+"/"+f来代替文件名。你也可以用你想要的任何字符串条件替换f.endswith(".jpg")

在“path/to/images”中扩展名为“jpg”和“png”的文件名:

import os
accepted_extensions = ["jpg", "png"]
filenames = [fn for fn in os.listdir("path/to/images") if fn.split(".")[-1] in accepted_extensions]

使用glob模块的过滤器:

进口一滴

import glob

通配符:

files=glob.glob("data/*")
print(files)


Out:


['data/ks_10000_0', 'data/ks_1000_0', 'data/ks_100_0', 'data/ks_100_1',
'data/ks_100_2', 'data/ks_106_0', 'data/ks_19_0', 'data/ks_200_0', 'data/ks_200_1',
'data/ks_300_0', 'data/ks_30_0', 'data/ks_400_0', 'data/ks_40_0', 'data/ks_45_0',
'data/ks_4_0', 'data/ks_500_0', 'data/ks_50_0', 'data/ks_50_1', 'data/ks_60_0',
'data/ks_82_0', 'data/ks_lecture_dp_1', 'data/ks_lecture_dp_2']

Fiter扩展.txt:

files = glob.glob("/home/ach/*/*.txt")

单个字符

glob.glob("/home/ach/file?.txt")

数量范围

glob.glob("/home/ach/*[0-9]*")

字母范围

glob.glob("/home/ach/[a-c]*")

你可以使用在Python标准库3.4及以上版本中可用的pathlib

from pathlib import Path


files = [f for f in Path.cwd().iterdir() if f.match("145592*.jpg")]

您可以定义模式并检查它。在这里,我已经采取了开始和结束模式,并在文件名中寻找它们。FILES包含目录中所有文件的列表。

import os
PATTERN_START = "145592"
PATTERN_END = ".jpg"
CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
for r,d,FILES in os.walk(CURRENT_DIR):
for FILE in FILES:
if PATTERN_START in FILE.startwith(PATTERN_START) and PATTERN_END in FILE.endswith(PATTERN_END):
print FILE

您可以使用列表推导式和其中的正则表达式检查器来简化它,包括带有指定后缀的图像文件。

import re
import os


dir_name = "."
files = [os.path.join(dir_name, f) for f in os.listdir(dir_name) if re.match(r'.*\.(jpg|jpeg|png)', f)]