program tip

파이썬은 여러 파일 형식을 가져옵니다

radiobox 2020. 7. 28. 08:21
반응형

파이썬은 여러 파일 형식을 가져옵니다


python에서 glob.glob를 사용하여 .txt, .mdown 및 .markdown과 같은 여러 파일 유형 목록을 얻는 더 좋은 방법이 있습니까? 지금 나는 이와 같은 것을 가지고있다 :

projectFiles1 = glob.glob( os.path.join(projectDir, '*.txt') )
projectFiles2 = glob.glob( os.path.join(projectDir, '*.mdown') )
projectFiles3 = glob.glob( os.path.join(projectDir, '*.markdown') )

더 좋은 방법이 있지만 어떻습니까?

>>> import glob
>>> types = ('*.pdf', '*.cpp') # the tuple of file types
>>> files_grabbed = []
>>> for files in types:
...     files_grabbed.extend(glob.glob(files))
... 
>>> files_grabbed   # the list of pdf and cpp files

다른 방법이있을 수 있으므로 다른 사람이 더 나은 답변을 얻을 수 있도록 기다립니다.


from glob import glob

files = glob('*.gif')
files.extend(glob('*.png'))
files.extend(glob('*.jpg'))

print(files)

경로를 지정해야하는 경우 일치 패턴을 반복하고 단순성을 위해 루프 내부의 결합을 유지하십시오.

from os.path import join
from glob import glob

files = []
for ext in ('*.gif', '*.png', '*.jpg'):
   files.extend(glob(join("path/to/dir", ext)))

print(files)

결과를 연결하십시오 :

import itertools as it, glob

def multiple_file_types(*patterns):
    return it.chain.from_iterable(glob.iglob(pattern) for pattern in patterns)

그때:

for filename in multiple_file_types("*.txt", "*.sql", "*.log"):
    # do stuff

glob 리스트를 반환합니다. 왜 여러 번 실행하고 결과를 연결하지 않습니까?

from glob import glob
ProjectFiles = glob('*.txt') + glob('*.mdown') + glob('*markdown')

glob으로는 불가능합니다. 당신은 오직 사용할 수 있습니다 :
* 모든 것과 일치
합니까? 모든 단일 문자와 일치
[seq] seq의 모든 문자와 일치
[! seq]는 seq에없는 모든 문자와 일치

os.listdir 및 regexp를 사용하여 패턴을 확인하십시오.

for x in os.listdir('.'):
  if re.match('.*\.txt|.*\.sql', x):
    print x

예를 들어, 위해 *.mp3*.flac여러 폴더에, 당신은 할 수 있습니다 :

mask = r'music/*/*.[mf][pl][3a]*'
glob.glob(mask)

이 아이디어는 더 많은 파일 확장자로 확장 될 수 있지만 , 조합이 해당 폴더에있을 수있는 다른 원치 않는 파일 확장자와 일치하지 않는지 확인해야합니다. 따라서 조심 하십시오.

임의의 확장자 목록을 단일 glob 패턴으로 자동 결합하려면 다음을 수행하십시오.

mask_base = r'music/*/*.'
exts = ['mp3', 'flac', 'wma']
chars = ''.join('[{}]'.format(''.join(set(c))) for c in zip(*exts))
mask = mask_base + chars + ('*' if len(set(len(e) for e in exts)) > 1 else '')
print(mask)  # music/*/*.[fmw][plm][3a]*

하나의 라이너, 그냥 지옥 ..

folder = "C:\\multi_pattern_glob_one_liner"
files = [item for sublist in [glob.glob(folder + ext) for ext in ["/*.txt", "/*.bat"]] for item in sublist]

산출:

['C:\\multi_pattern_glob_one_liner\\dummy_txt.txt', 'C:\\multi_pattern_glob_one_liner\\dummy_bat.bat']

도움을 받기 위해 여기에 온 후, 나는 나만의 솔루션을 만들어 공유하고 싶었습니다. user2363986의 답변을 기반으로하지만 더 확장 가능하다고 생각합니다. 즉, 확장명이 1000 개인 경우에도 코드는 다소 우아하게 보입니다.

from glob import glob

directoryPath  = "C:\\temp\\*." 
fileExtensions = [ "jpg", "jpeg", "png", "bmp", "gif" ]
listOfFiles    = []

for extension in fileExtensions:
    listOfFiles.extend( glob( directoryPath + extension ))

for file in listOfFiles:
    print(file)   # Or do other stuff

이것은 Python 3.4+ pathlib솔루션입니다.

exts = ".pdf", ".doc", ".xls", ".csv", ".ppt"
filelist = (str(i) for i in map(pathlib.Path, os.listdir(src)) if i.suffix.lower() in exts and not i.stem.startswith("~"))

또한로 시작하는 모든 파일 이름은 무시합니다 ~.


다음은 Pat의 답변에 대한 한 줄의 목록 이해 변형입니다 (특정 프로젝트 디렉토리에서 가져오고 싶었던 것도 포함).

import os, glob
exts = ['*.txt', '*.mdown', '*.markdown']
files = [f for ext in exts for f in glob.glob(os.path.join(project_dir, ext))]

확장명 ( for ext in exts)을 반복 한 다음 각 확장명에 대해 각 패턴 ( for f in glob.glob(os.path.join(project_dir, ext))과 일치하는 각 파일을 가져옵니다 .

이 솔루션은 짧고 불필요한 for 루프, 중첩 목록 이해 또는 코드를 어지럽히는 기능이 없습니다. 순수하고 표현력있는 파이톤 입니다.

이 솔루션을 사용하면 exts코드를 업데이트하지 않고도 사용자 정의 목록을 변경할 수 있습니다. (이것은 항상 좋은 습관입니다!)

list-comprehension은 Laurent의 솔루션 (투표 한)과 동일합니다. 그러나 별도의 기능으로 한 줄을 제외하는 것이 일반적으로 필요하지 않다고 주장하므로 대안 솔루션으로 제공하고 있습니다.

보너스:

단일 디렉토리뿐만 아니라 모든 서브 디렉토리도 검색해야하는 경우 recursive=True다중 디렉토리 glob 기호 ** 1을 전달 하고 사용할 수 있습니다 .

files = [f for ext in exts 
         for f in glob.glob(os.path.join(project_dir, '**', ext), recursive=True)]

이것은 glob.glob('<project_dir>/**/*.txt', recursive=True)각 확장에 대해 호출됩니다 .

1 기술적으로 **glob 기호는 슬래시를 포함하여 하나 이상의 문자와 일치 /합니다 (단일 *glob 기호 와 달리 ). 실제로는 **슬래시 (경로 구분 기호)로 둘러싸면 0 개 이상의 디렉토리와 일치 한다는 사실 만 기억하면됩니다 .


files = glob.glob('*.txt')
files.extend(glob.glob('*.dat'))

확장 프로그램 수만큼 여러 번 글로브하는 것을 제안하는 많은 답변이 있습니다.

from pathlib import Path

files = {p.resolve() for p in Path(path).glob("**/*") if p.suffix in [".c", ".cc", ".cpp", ".hxx", ".h"]}

Apache Ant의 FileSet 및 Globs와 유사한 방식으로 여러 포함을 구현하는 Formic출시 했습니다 .

검색을 구현할 수 있습니다 :

import formic
patterns = ["*.txt", "*.markdown", "*.mdown"]
fileset = formic.FileSet(directory=projectDir, include=patterns)
for file_name in fileset.qualified_files():
    # Do something with file_name

전체 Ant glob가 구현되었으므로 각 패턴마다 다른 디렉토리를 포함 할 수 있으므로 하나의 서브 디렉토리에서 해당 .txt 파일 만 선택하고 다른 서브 디렉토리에서는 .markdown 만 선택할 수 있습니다.

patterns = [ "/unformatted/**/*.txt", "/formatted/**/*.mdown" ]

이게 도움이 되길 바란다.


아니 glob,하지만 여기에 지능형리스트를 사용하여 다른 방법이있다 :

extensions = 'txt mdown markdown'.split()
projectFiles = [f for f in os.listdir(projectDir) 
                  if os.path.splitext(f)[1][1:] in extensions]

다음 _glob은 여러 파일 확장자를위한 기능입니다.

import glob
import os
def _glob(path, *exts):
    """Glob for multiple file extensions

    Parameters
    ----------
    path : str
        A file name without extension, or directory name
    exts : tuple
        File extensions to glob for

    Returns
    -------
    files : list
        list of files matching extensions in exts in path

    """
    path = os.path.join(path, "*") if os.path.isdir(path) else path + "*"
    return [f for files in [glob.glob(path + ext) for ext in exts] for f in files]

files = _glob(projectDir, ".txt", ".mdown", ".markdown")

glob여러 파일 형식 을 사용하려면 glob()루프에서 함수를 여러 번 호출해야합니다 . 이 함수는 목록을 반환하므로 목록을 연결해야합니다.

예를 들어이 함수는 다음 작업을 수행합니다.

import glob
import os


def glob_filetypes(root_dir, *patterns):
    return [path
            for pattern in patterns
            for path in glob.glob(os.path.join(root_dir, pattern))]

간단한 사용법 :

project_dir = "path/to/project/dir"
for path in sorted(glob_filetypes(project_dir, '*.txt', '*.mdown', '*.markdown')):
    print(path)

glob.iglob()반복자를 사용 하는 데 사용할 수도 있습니다 .

실제로 모든 값을 동시에 저장하지 않고 glob ()와 동일한 값을 생성하는 반복자를 반환합니다.

def iglob_filetypes(root_dir, *patterns):
    return (path
            for pattern in patterns
            for path in glob.iglob(os.path.join(root_dir, pattern)))

기존 확장과 필요한 확장을 비교하여 수동 목록을 만들 수 있습니다.

ext_list = ['gif','jpg','jpeg','png'];
file_list = []
for file in glob.glob('*.*'):
  if file.rsplit('.',1)[1] in ext_list :
    file_list.append(file)

필터를 사용할 수 있습니다 :

import os
import glob

projectFiles = filter(
    lambda x: os.path.splitext(x)[1] in [".txt", ".mdown", ".markdown"]
    glob.glob(os.path.join(projectDir, "*"))
)

다음 reduce()과 같이 사용할 수도 있습니다 .

import glob
file_types = ['*.txt', '*.mdown', '*.markdown']
project_files = reduce(lambda list1, list2: list1 + list2, (glob.glob(t) for t in file_types))

그러면 glob.glob()각 패턴에 대한 목록이 만들어 지고 단일 목록으로 줄어 듭니다.


import os    
import glob
import operator
from functools import reduce

types = ('*.jpg', '*.png', '*.jpeg')
lazy_paths = (glob.glob(os.path.join('my_path', t)) for t in types)
paths = reduce(operator.add, lazy_paths, [])

https://docs.python.org/3.5/library/functools.html#functools.reduce https://docs.python.org/3.5/library/operator.html#operator.add


하나의 글로브, 많은 확장명 ...하지만 불완전한 솔루션 (다른 파일과 일치 할 수 있음).

filetypes = ['tif', 'jpg']

filetypes = zip(*[list(ft) for ft in filetypes])
filetypes = ["".join(ch) for ch in filetypes]
filetypes = ["[%s]" % ch for ch in filetypes]
filetypes = "".join(filetypes) + "*"
print(filetypes)
# => [tj][ip][fg]*

glob.glob("/path/to/*.%s" % filetypes)

나는 같은 문제가 있었고 이것이 내가 생각해 낸 것입니다.

import os, sys, re

#without glob

src_dir = '/mnt/mypics/'
src_pics = []
ext = re.compile('.*\.(|{}|)$'.format('|'.join(['png', 'jpeg', 'jpg']).encode('utf-8')))
for root, dirnames, filenames in os.walk(src_dir):
  for filename in filter(lambda name:ext.search(name),filenames):
    src_pics.append(os.path.join(root, filename))

예를 들면 다음과 같습니다.

import glob
lst_img = []
base_dir = '/home/xy/img/'

# get all the jpg file in base_dir 
lst_img += glob.glob(base_dir + '*.jpg')
print lst_img
# ['/home/xy/img/2.jpg', '/home/xy/img/1.jpg']

# append all the png file in base_dir to lst_img
lst_img += glob.glob(base_dir + '*.png')
print lst_img
# ['/home/xy/img/2.jpg', '/home/xy/img/1.jpg', '/home/xy/img/3.png']

기능 :

import glob
def get_files(base_dir='/home/xy/img/', lst_extension=['*.jpg', '*.png']):
    """
    :param base_dir:base directory
    :param lst_extension:lst_extension: list like ['*.jpg', '*.png', ...]
    :return:file lists like ['/home/xy/img/2.jpg','/home/xy/img/3.png']
    """
    lst_files = []
    for ext in lst_extension:
        lst_files += glob.glob(base_dir+ext)
    return lst_files

확장명 목록을 사용하고 반복

from os.path import join
from glob import glob

files = ['*.gif', '*.png', '*.jpg']
for ext in files:
   files.extend(glob(join("path/to/dir", ext)))

print(files)

또 다른 해결책은 (사용하는 glob여러 일치를 사용하여 경로를 얻을 수 patterns및 사용하여 하나의 목록으로 모든 경로를 결합 reduce하고 add) :

import functools, glob, operator
paths = functools.reduce(operator.add, [glob.glob(pattern) for pattern in [
    "path1/*.ext1",
    "path2/*.ext2"]])

사용하는 경우 다음을 pathlib시도하십시오.

import pathlib

extensions = ['.py', '.txt']
root_dir = './test/'

files = filter(lambda p: p.suffix in extensions, pathlib.Path(root_dir).glob('**/*'))

print(list(files))

경험적 테스트에서 얻은 결과에 따르면 glob.glob확장명으로 파일을 필터링하는 더 좋은 방법은 아닙니다. 그 이유 중 일부는 다음과 같습니다.

  • gloving " language "는 다중 확장을 완벽하게 지정할 수 없습니다.
  • 전자는 파일 확장자에 따라 잘못된 결과를 얻습니다.
  • globbing 방법은 다른 대부분의 방법보다 느리게 경험적으로 입증되었습니다.
  • 다른 파일 시스템 객체라도 " 확장자 "를 가질 수있는 것이 이상하더라도 폴더도 마찬가지입니다.

4확장명으로 파일을 필터링하고 파일을 넣는 다음과 같은 다양한 방법을 테스트했습니다 (시간의 정확성과 효율성) list.

from glob import glob, iglob
from re import compile, findall
from os import walk


def glob_with_storage(args):

    elements = ''.join([f'[{i}]' for i in args.extensions])
    globs = f'{args.target}/**/*{elements}'
    results = glob(globs, recursive=True)

    return results


def glob_with_iteration(args):

    elements = ''.join([f'[{i}]' for i in args.extensions])
    globs = f'{args.target}/**/*{elements}'
    results = [i for i in iglob(globs, recursive=True)]

    return results


def walk_with_suffixes(args):

    results = []
    for r, d, f in walk(args.target):
        for ff in f:
            for e in args.extensions:
                if ff.endswith(e):
                    results.append(path_join(r,ff))
                    break
    return results


def walk_with_regs(args):

    reg = compile('|'.join([f'{i}$' for i in args.extensions]))

    results = []
    for r, d, f in walk(args.target):
        for ff in f:
            if len(findall(reg,ff)):
                results.append(path_join(r, ff))

    return results

By running the code above on my laptop I obtained the following auto-explicative results.

Elapsed time for '7 times glob_with_storage()':  0.365023 seconds.
mean   : 0.05214614
median : 0.051861
stdev  : 0.001492152
min    : 0.050864
max    : 0.054853

Elapsed time for '7 times glob_with_iteration()':  0.360037 seconds.
mean   : 0.05143386
median : 0.050864
stdev  : 0.0007847381
min    : 0.050864
max    : 0.052859

Elapsed time for '7 times walk_with_suffixes()':  0.26529 seconds.
mean   : 0.03789857
median : 0.037899
stdev  : 0.0005759071
min    : 0.036901
max    : 0.038896

Elapsed time for '7 times walk_with_regs()':  0.290223 seconds.
mean   : 0.04146043
median : 0.040891
stdev  : 0.0007846776
min    : 0.04089
max    : 0.042885

Results sizes:
0 2451
1 2451
2 2446
3 2446

Differences between glob() and walk():
0 E:\x\y\z\venv\lib\python3.7\site-packages\Cython\Includes\numpy
1 E:\x\y\z\venv\lib\python3.7\site-packages\Cython\Utility\CppSupport.cpp
2 E:\x\y\z\venv\lib\python3.7\site-packages\future\moves\xmlrpc
3 E:\x\y\z\venv\lib\python3.7\site-packages\Cython\Includes\libcpp
4 E:\x\y\z\venv\lib\python3.7\site-packages\future\backports\xmlrpc

Elapsed time for 'main':  1.317424 seconds.

The fastest way to filter out files by extensions, happens even to be the ugliest one. Which is, nested for loops and string comparison using the endswith() method.

Moreover, as you can see, the globbing algorithms (with the pattern E:\x\y\z\**/*[py][pyc]) even with only 2 extension given (py and pyc) returns also incorrect results.


This Should Work:

import glob
extensions = ('*.txt', '*.mdown', '*.markdown')
for i in extensions:
    for files in glob.glob(i):
        print (files)

this worked for me:

import glob
images = glob.glob('*.JPG' or '*.jpg' or '*.png')

참고URL : https://stackoverflow.com/questions/4568580/python-glob-multiple-filetypes

반응형