Подтвердить что ты не робот

Удаление нескольких файлов, соответствующих шаблону

Я сделал онлайн-галерею, используя Python и Django. Я только начал добавлять функции редактирования, начиная с вращения. Я использую sorl.thumbnail для автоматического создания эскизов по запросу.

Когда я редактирую исходный файл, мне нужно очистить все миниатюры, чтобы они генерировались. Есть три или четыре из них на изображение (у меня разные для разных случаев).

Я мог бы жестко закодировать в переменных файлах... Но это беспорядочно, и если я изменю способ, которым я что-то делаю, мне нужно будет пересмотреть код.

В идеале я хотел бы сделать regex-delete. В терминах регулярных выражений все мои оригиналы называются так:

^(?P<photo_id>\d+)\.jpg$

Итак, я хочу удалить:

^(?P<photo_id>\d+)[^\d].*jpg$

(Где я заменяю photo_id идентификатором, который хочу очистить.)

4b9b3361

Ответ 1

Попробуйте что-то вроде этого:

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

Вариант подхода 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()

Ответ 3

Если вам нужна рекурсия в несколько подкаталогов, вы можете использовать этот метод:

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, который содержит список подкаталогов для посещения на каждом node.

Обратите внимание, что если вы находитесь в каталоге, вы также можете получить файлы, соответствующие простому выражению шаблона, с помощью glob.glob(pattern). В этом случае вам придется вычесть набор файлов для хранения всего набора, поэтому приведенный выше код более эффективен.

Ответ 4

Как насчет этого?

import glob, os, multiprocessing
p = multiprocessing.Pool(4)
p.map(os.remove, glob.glob("P*.jpg"))

Помните, что это не делает рекурсии и использует подстановочные знаки (не регулярное выражение).

Ответ 5

Мне непонятно, что вы действительно хотите выполнить любое сопоставление именованной группы - при использовании, которое вы описываете, фотоид является входом в функцию удаления, а назначение названных групп - "вывод", т.е. извлечение определенные подстроки из согласованной строки (и доступ к ним по имени в объекте совпадения). Поэтому я бы рекомендовал более простой подход:

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)

Вы можете передать фотоид как обычную строку или как часть образца RE, если вам нужно удалить сразу несколько подходящих идентификаторов (например, r'abc[def], чтобы удалить abcd, abce и abcf за один вызов) - что причина, по которой я вставляю его буквально в шаблон RE, вместо того, чтобы вставлять строку re.escape(photoid), как это было бы обычной практикой. Некоторые части, такие как подсчет количества удалений и возвращение информационного сообщения в конце, являются, очевидно, излишествами, которые вы должны удалить, если они не дают вам никакой добавленной стоимости в вашем прецеденте.

Другие, такие как шаблон "if not...//continue", рекомендуются в Python (плоская лучше, чем вложенная: выпрыгивая на следующую ногу цикла, как только вы определяете, нет ничего сделать это лучше, чем вложенные действия, выполняемые в if), хотя, конечно, будут работать и другие механизмы кода.

Ответ 6

Мое одобрение:

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)

Это будет рекурсивно удалять каждый файл, который соответствует шаблону по умолчанию, и каждый файл, который не имеет, если включен, является истинным. Затем он удалит все пустые папки из дерева каталогов.

Ответ 7

Я нахожу Popen(["rm " + file_name + "*.ext"], shell=True, stdout=PIPE).communicate() более простым решением этой проблемы. Хотя это подвержено атакам с инъекциями, я не вижу никаких проблем, если ваша программа использует это внутри.

Ответ 8

def recursive_purge(dir, pattern):
    for f in os.listdir(dir):
        if os.path.isdir(os.path.join(dir, f)):
            recursive_purge(os.path.join(dir, f), pattern)
        elif re.search(pattern, os.path.join(dir, f)):
            os.remove(os.path.join(dir, f))