UFO ET IT

패턴과 일치하는 여러 파일 삭제

ufoet 2020. 11. 29. 12:42
반응형

패턴과 일치하는 여러 파일 삭제


Python과 Django를 사용하여 온라인 갤러리를 만들었습니다. 회전부터 시작하여 편집 기능을 추가하기 시작했습니다. sorl.thumbnail을 사용하여 필요에 따라 미리보기 이미지를 자동 생성합니다.

원본 파일을 편집 할 때 새 섬네일이 생성되도록 모든 섬네일을 정리해야합니다. 이미지 당 3 개 또는 4 개가 있습니다 (다른 경우에 따라 다릅니다).

내가 할 수 파일 - varients ...하지만 그의 지저분한에서 하드 코드와 내가 일을 할 방법을 변경하는 경우, 내가 코드를 다시 방문해야합니다.

이상적으로 정규식 삭제를하고 싶습니다. 정규식 용어로 내 모든 원본의 이름은 다음과 같습니다.

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

그래서 삭제하고 싶습니다.

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

(내가 photo_id청소하고 싶은 ID로 대체 합니다.)


다음과 같이 시도하십시오.

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))

그런 다음 일치하려는 파일과 패턴이 포함 된 디렉토리를 전달합니다.


Python 3에서 작동하는 glob 접근 방식의 변형입니다.

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()

여러 하위 디렉터리에 대한 재귀가 필요한 경우 다음 방법을 사용할 수 있습니다.

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). 이 경우 전체 세트에서 유지할 파일 세트를 빼야하므로 위의 코드가 더 효율적입니다.


이건 어때?

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")))

나는 그것이 가장 기능적인 방법은 아니지만 간결하고 일을 수행한다는 데 동의합니다.


명명 된 그룹 일치를 실제로 수행하고 싶은지 확실하지 않습니다. 설명하는 용도에서 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)

You can pass the photoid as a normal string, or as a RE pattern piece if you need to remove several matchable IDs at once (e.g., r'abc[def] to remove abcd, abce, and abcf in a single call) -- that's the reason I'm inserting it literally in the RE pattern, rather than inserting the string re.escape(photoid) as would be normal practice. Certain parts such as counting the number of deletions and returning an informative message at the end are obviously frills which you should remove if they give you no added value in your use case.

Others, such as the "if not ... // continue" pattern, are highly recommended practice in Python (flat is better than nested: bailing out to the next leg of the loop as soon as you determine there is nothing to do on this one is better than nesting the actions to be done within an if), although of course other arrangements of the code would work too.


My recomendation:

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)

This will recursively remove every file that matches the pattern by default, and every file that doesn't if inclusive is true. It will then remove any empty folders from the directory tree.


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)

I find Popen(["rm " + file_name + "*.ext"], shell=True, stdout=PIPE).communicate() to be a much simpler solution to this problem. Although this is prone to injection attacks, I don't see any issues if your program is using this internally.


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))

참고URL : https://stackoverflow.com/questions/1548704/delete-multiple-files-matching-a-pattern

반응형