我使用Python和Django建立了一个在线画廊。我刚开始添加编辑功能,从旋转开始。我使用sorl.thumbnail按需自动生成缩略图。
当我编辑原始文件时,我需要清理所有缩略图,以便生成新的缩略图。每张图片中有三个或四个(我在不同场合有不同的图像)。
我可以在文件变量中进行硬编码...但是这很麻烦,如果我改变了我的工作方式,我需要重新访问代码。
理想情况下,我想要进行正则表达式删除。在正则表达式术语中,我的所有原件都是这样命名的:
^(?P<photo_id>\d+)\.jpg$
所以我想删除:
^(?P<photo_id>\d+)[^\d].*jpg$
(我用我要清理的ID替换photo_id
。)
答案 0 :(得分:66)
glob方法的变体,适用于Python 3:
import glob, os
for f in glob.glob("P*.jpg"):
os.remove(f)
编辑:在Python 3.4+中,您可能希望使用pathlib:
from pathlib import Path
for p in Path(".").glob("P*.jpg"):
p.unlink()
答案 1 :(得分:56)
尝试这样的事情:
import os, re
def purge(dir, pattern):
for f in os.listdir(dir):
if re.search(pattern, f):
os.remove(os.path.join(dir, f))
然后你将传递包含文件和你想要匹配的模式的目录。
答案 2 :(得分:11)
如果需要递归到多个子目录,可以使用此方法:
import os, re, os.path
pattern = "^(?P<photo_id>\d+)[^\d].*jpg$"
mypath = "Photos"
for root, dirs, files in os.walk(mypath):
for file in filter(lambda x: re.match(pattern, x), files):
os.remove(os.path.join(root, file))
您可以安全地从dirs
中删除子目录,其中包含要在每个节点访问的子目录列表。
请注意,如果您在目录中,还可以使用glob.glob(pattern)
获取与简单模式表达式相对应的文件。在这种情况下,您必须减去文件集以保留整个集合,因此上面的代码更有效。
答案 3 :(得分:8)
这个怎么样?
import glob, os, multiprocessing
p = multiprocessing.Pool(4)
p.map(os.remove, glob.glob("P*.jpg"))
请注意,这不会进行递归并使用通配符(而不是正则表达式)。
<强>更新强>
在Python 3中,map()
函数将返回迭代器,而不是列表。这很有用,因为您可能希望对项目进行某种处理,并且迭代器总是会为此节省更多内存。
但是,如果列表是真正所需要的,请执行以下操作:
...
list(p.map(os.remove, glob.glob("P*.jpg")))
我同意这不是最有效的方式,但它很简洁并且能够胜任。
答案 4 :(得分:2)
我不清楚你真的想要进行任何命名组匹配 - 在你描述的用途中,photoid是删除函数的输入,命名组的目的是“输出”,即从匹配的字符串中提取某些子字符串(并在匹配对象中按名称访问它们)。所以,我建议采用一种更简单的方法:
import re
import os
def delete_thumbnails(photoid, photodirroot):
matcher = re.compile(r'^%s\d+\D.*jpg$' % photoid)
numdeleted = 0
for rootdir, subdirs, filenames in os.walk(photodirroot):
for name in filenames:
if not matcher.match(name):
continue
path = os.path.join(rootdir, name)
os.remove(path)
numdeleted += 1
return "Deleted %d thumbnails for %r" % (numdeleted, photoid)
如果您需要一次删除多个匹配的ID(例如,r'abc[def]
以在一次调用中删除abcd,abce和abcf),您可以将photoid作为普通字符串传递,或者作为RE模式传递 - 这就是我将它插入RE模式中的原因,而不是像通常的做法那样插入字符串re.escape(photoid)
。某些部分,例如计算删除次数和最后返回信息性消息,显然是你应该删除的褶边,如果它们在你的用例中没有给你增加价值。
其他人,例如“if not ... // continue”模式,在Python中是强烈推荐的做法(平坦优于嵌套:一旦确定没有任何内容,就会挽救循环的下一个循环要做到这一点比在if
内嵌套要完成的操作更好,尽管当然其他代码的安排也会起作用。
答案 5 :(得分:2)
我的推荐:
def purge(dir, pattern, inclusive=True):
regexObj = re.compile(pattern)
for root, dirs, files in os.walk(dir, topdown=False):
for name in files:
path = os.path.join(root, name)
if bool(regexObj.search(path)) == bool(inclusive):
os.remove(path)
for name in dirs:
path = os.path.join(root, name)
if len(os.listdir(path)) == 0:
os.rmdir(path)
默认情况下,这将递归删除与模式匹配的每个文件,如果包含,则每个文件都不为true。然后它将从目录树中删除任何空文件夹。
答案 6 :(得分:1)
import os, sys, glob, re
def main():
mypath = "<Path to Root Folder to work within>"
for root, dirs, files in os.walk(mypath):
for file in files:
p = os.path.join(root, file)
if os.path.isfile(p):
if p[-4:] == ".jpg": #Or any pattern you want
os.remove(p)
答案 7 :(得分:0)
我发现Popen(["rm " + file_name + "*.ext"], shell=True, stdout=PIPE).communicate()
是解决此问题的更简单方法。虽然这很容易受到注入攻击,但如果您的程序在内部使用它,我不会发现任何问题。
答案 8 :(得分:0)
5.1