質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

zip

ZIPとは、複数のファイルをひとつにまとめて圧縮したり、圧縮したファイルを展開することができるアーカイブフォーマットです。 1998年以降のWindowsOS各バージョンで、標準の圧縮フォルダとして採用されています。 MacOSでも、X v10.3以降に他の圧縮ソフトとまとめてZIP機能を採用しています。

Q&A

解決済

4回答

1503閲覧

Pythonで、正規表現を使って特定条件だけZIPファイルに追加したい

ky_46

総合スコア92

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

zip

ZIPとは、複数のファイルをひとつにまとめて圧縮したり、圧縮したファイルを展開することができるアーカイブフォーマットです。 1998年以降のWindowsOS各バージョンで、標準の圧縮フォルダとして採用されています。 MacOSでも、X v10.3以降に他の圧縮ソフトとまとめてZIP機能を採用しています。

0グッド

0クリップ

投稿2018/05/04 15:16

Pythonで、正規表現を使って特定条件だけZIPファイルに追加したい

前提・実現したいこと

pythonで指定ディレクトリの中からファイルを選んでZIPファイルに格納したい

発生している問題

image_1.jpg
image_2.jpg
image_3.jpg'
image-cv01.jpg
image-cv21.jpg
image-cv31.jpg
image.jpg
image_100.jpg

例として、上記のようなファイルリストがあったとします。
数字の部分は決まった形式なので変わることはありませんが、数字の最大値は状況により変わります。

これから

image_3.jpg'
image-cv01.jpg
image-cv21.jpg
image-cv31.jpg

を格納したsyoko.zipを作成するのが希望動作です。

つまり、image_[数字一桁]なら最大値のファイルのみ、image-cv[数字二桁]なら全ファイルを追加。imageだけで何もないファイルや、_[数字三桁]などは圧縮ファイルへ追加しないという動作になります。

該当のソースコード

Python

1 2wodir = '上記のファイルが格納されたフォルダを指定' 3files = [] 4 5#直下のファイル一覧取得 6 for x in os.listdir(wodir): 7 if os.path.isfile(wodir + x): 8 files.append(x) 9 10 11 compFile01 = zipfile.ZipFile(syoko.zip', 'w', zipfile.ZIP_DEFLATED) 12 for y in files: 13 pattern = 'image' + r"_[0-9]{1}.jpg" 14 matchOB = re.match(pattern, y) 15 if matchOB: # ファイル名がパターンとマッチしたら追加 16 compFile01.write(y) 17 18 pattern = 'image' + r"-cv[0-9]{2}.jpg" 19 matchOB = re.match(pattern, y) 20 if matchOB: # ファイル名がパターンとマッチしたら追加 21 compFile02.write(y) 22 23 compFile01.close() 24

結果、出来上がったsyoko.zipは、
image_1.jpg
image_2.jpg
image_3.jpg'
image-cv01.jpg
image-cv21.jpg
image-cv31.jpg

のようにimage_[数字1文字]のファイルを全部ひっかけてしまいます。

いろいろGoogleなどで調べてみたのですが、数字一桁の最も大きいものだけを抽出する方法が見つけられません。

あるいは、pythonでzipから指定したファイルを削除できれば、とも思ったのですが、上記コードで最大値を確保する方法や、圧縮ファイルからファイルを除去する方法も見つけられずにおります。

よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

結局のところ対処すべきは2パターンのみ。
正規表現よりもglobを使ったほうがシンプルな気がします。

python

1import glob 2import zipfile 3 4targets = [] 5 6for f in sorted(glob.glob("./image_?.jpg")): 7 target=f 8targets.append(target) 9 10for f in glob.glob("./image_cv??.jpg"): 11 targets.append(f) 12 13compFile01 = zipfile.ZipFile('syoko.zip', 'w') 14for y in targets: 15 compFile01.write(y) 16compFile01.close() 17 18

投稿2018/05/04 18:37

KojiDoi

総合スコア13671

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ky_46

2018/05/05 06:20

glob というのはGoogleで得られなかったので、知識として助かりました。今回の質問範囲と違うので情報に入れなかったのですが、実はこの後、zipに格納しなかったimage.jpg とimage_100.jpgを指定のフォルダに移動する作業があるので、それを組み込みするとき使えそうです。ありがとうございます。
guest

0

python

1pattern1 = re.compile(r'^image_[0-9]{1}.jpg$') 2pattern2 = re.compile(r'^image-cv[0-9]{2}.jpg$') 3comp_files = sorted([file for file in files if pattern1.match(file)])[-1:] + [file for file in files if pattern2.match(file)] 4print(comp_files) 5#['image_3.jpg', 'image-cv01.jpg', 'image-cv21.jpg', 'image-cv31.jpg']

投稿2018/05/04 15:55

編集2018/05/04 15:55
gingertail

総合スコア317

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ky_46

2018/05/05 06:15

ご回答ありがとうございます。今回はhayataka2049様の方法で解決といたしました。感謝です。
guest

0

ファイル一覧をソートして、
image_[数字一桁]のパターンのファイルは。その最後のものだけを対象にするようにしました。
さらに subfolder にも対応させてみました。

a.py

python

1import os 2import re 3import zipfile 4 5def file_filter(files): 6 target_1 = None 7 targets = [] 8 for file in sorted(files): 9 pattern = r"image\_[0-9].jpg" 10 if re.match(pattern, file): 11 target_1 = file 12 next 13 pattern = r"image\-cv[0-9]{2}.jpg" 14 if re.match(pattern, file): 15 targets.append(file) 16 17 if target_1: 18 targets.append(target_1) 19 return targets 20 21 22src_dir = "data" 23zip_path = "syoko.zip" 24with zipfile.ZipFile(zip_path, 'w') as zip_file: 25 for folder, subfolders, files in os.walk(src_dir): 26 target_files = file_filter(files) 27 28 if len(target_files) > 0: 29 zip_file.write(folder) 30 for file in target_files: 31 zip_file.write(os.path.join(folder, file))

実行例

イメージ説明

イメージ説明

参考情報:

  • Pythonで指定フォルダ配下のサブフォルダとファイルを全てZIP圧縮する方法

https://tonari-it.com/python-zipfile-walk/

投稿2018/05/04 23:43

katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ky_46

2018/05/05 06:25

ありがとうございます。今回はhayataka2049様の方法で解決といたしました。ただ、サブフォルダ処理は今後、参考にさせていただきます。
guest

0

ベストアンサー

  • 入れるべきファイル名は先に走査して決め、実際の処理は後でまとめて行う
  • image_[数字1文字]はとりあえずぜんぶ見てからmaxを取る

という方針で行きましょう。

python

1filename_lst1 = [] 2filename_lst2 = [] 3for y in files: 4 pattern = 'image' + r"_[0-9]{1}.jpg" 5 matchOB = re.match(pattern, y) 6 if matchOB: # ファイル名がパターンとマッチしたら追加 7 filename_lst1.append(y) 8 9 pattern = 'image' + r"-cv[0-9]{2}.jpg" 10 matchOB = re.match(pattern, y) 11 if matchOB: # ファイル名がパターンとマッチしたら追加 12 filename_lst2.append(y) 13 14max_filename = max(filename_lst1, key=lambda x:int(x[6])) 15 16compFile01 = zipfile.ZipFile('syoko.zip', 'w', zipfile.ZIP_DEFLATED) 17for y in filename_lst2 + [max_filename]: 18 compFile01.write(y) 19compFile01.close()

投稿2018/05/04 15:37

hayataka2049

総合スコア30933

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ky_46

2018/05/05 06:11

ご回答ありがとうございます。 > max_filename = max(filename_lst1, key=lambda x:int(x[6])) この部分は、「filename_lst1を、文字列を0から勘定して6番目を数字にしてソートする」という理解であっていますでしょうか? 試してみたところ、image_1の数字の部分を見事にソートして、最大値をひっかけました。 大変助かりました。ありがとうございます。
hayataka2049

2018/05/05 09:01

ソートするというか、そのまま最大値ですね
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問