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

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

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

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

1324閲覧

ファイル名を0埋めでリネームしたい

MHU_ME

総合スコア10

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2022/06/30 13:38

pythonでカレントフォルダ以下の階層にあるすべてのファイルに対して、ファイル名の中の数字を3桁にゼロ埋めした形にリネームしようとしています。

import glob import os import re for i in glob.glob('**',recursive=True): f=os.path.splitext(i)[0] d=re.findall('(\d+?)',f) for j in d: jj="{0:03d}".format(int(j)) f=re.sub(str(j),jj,f) print(i) print(f,"\n")

のようなコードを考えたのですが、下記のような結果になり、上手く行かないところがあります。
置換された桁数が一定していないのですが、どのように指定してあげればよいでしょうか?
ファイル中には、何か所数字が含まれているか分からないので、for j in d:でループして、ヒットしたdを全て拾う形にしていますが、このループの中で置換をしているのが良くないような感じがするものの、どう直せば良いか分からず、困っています。

以下、結果です。

06いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・1.mp3
000006いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ006\第005章~長い休日・001

06いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・10.mp3
0000000000000006いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ0000006\第0000005章~長い休日・0000001000000000

06いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・2.mp3
000006いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ006\第005章~長い休日・002

06いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・3.mp3
000006いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ006\第005章~長い休日・003

06いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・4.mp3
000006いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ006\第005章~長い休日・004

06いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・5.mp3
000006いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ006\第00005章~長い休日・00005

06いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・6.mp3
00000006いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ00006\第005章~長い休日・00006

06いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・7.mp3
000006いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ006\第005章~長い休日・007

06いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・8.mp3
000006いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ006\第005章~長い休日・008

06いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・9.mp3
000006いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ006\第005章~長い休日・009

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

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

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

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

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

y_waiwai

2022/06/30 13:54

それがどうなればいいというはなしなんでしょうか
MHU_ME

2022/06/30 14:00

06いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・1.mp3 であれば、 006いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ006\第005章~長い休日・001.mp3 (全ての数字の箇所を3桁のゼロ埋め) にリネームしたいです。
guest

回答2

0

ベストアンサー

提示コードでは文字列全体に対して複数回の置換を行っているので、意図しない結果になっています。
以下のようにsubに変換関数を指定することで、各マッチした部分に1回だけ置換操作をすることができます。
なお、以下では提示コードの変換規則をそのまま利用しているので全角006になります。

Python

1 2import os 3import re 4 5files = """06いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・1.mp3 606いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・10.mp3 706いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・2.mp3 806いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・3.mp3 906いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・4.mp3 1006いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・5.mp3 1106いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・6.mp3 1206いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・7.mp3 1306いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・8.mp3 1406いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・9.mp3""".split('\n') 15 16def rep(m): 17 s = m.group(0) 18 return '{0:03d}'.format(int(s)) 19 20for i in files: 21 f=os.path.splitext(i)[0] 22 print(f) 23 ret = re.sub(r'\d+', rep, f) 24 print(ret) 25""" 2606いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・1 27006いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ006\第005章~長い休日・001 2806いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・10 29006いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ006\第005章~長い休日・010 3006いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・2 31006いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ006\第005章~長い休日・002 3206いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・3 33006いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ006\第005章~長い休日・003 3406いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・4 35006いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ006\第005章~長い休日・004 3606いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・5 37006いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ006\第005章~長い休日・005 3806いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・6 39006いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ006\第005章~長い休日・006 4006いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・7 41006いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ006\第005章~長い休日・007 4206いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・8 43006いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ006\第005章~長い休日・008 4406いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・9 45006いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ006\第005章~長い休日・009 46"""

投稿2022/07/01 01:13

編集2022/07/01 01:23
can110

総合スコア38266

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

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

MHU_ME

2022/07/01 06:47

これです! 関数にするところまでは思いついたのですが、引数をどう渡すかで躓いていました。 正規表現オブジェクトが引数無しで受け渡される仕様なのですね。 知りませんでした。 ありがとうございました。
guest

0

正規表現を変えました。

diff

1- d=re.findall('(\d+?)',f) 2+ d=re.findall('([\d]{1,2})',f) 3# 06いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第5章~長い休日・1.mp3 4# 006いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ006\第005章~長い休日・001

投稿2022/06/30 16:15

meg_

総合スコア10580

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

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

MHU_ME

2022/06/30 20:59

ありがとうございます。 動かしてみて分かりましたが、自分が想定していたfor j in d:のループによる処理の方にも問題がありました。 このループ処理ですと、 06いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第4章~わたしたちの伝説の一冊・3.mp3 006いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ006\第004章~わたしたちの伝説の一冊・003 06いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ6\第4章~わたしたちの伝説の一冊・4.mp3 006いまさら翼といわれても~完全版オーディオブック〈古典部〉シリーズ006\第00004章~わたしたちの伝説の一冊・00004 のように、同じ数字が2か所以上にある場合に、0埋めの回数が増えてしまうようです。最初の06とシリーズ6は後者が全角になっているせいか、逆に正しく動作して3桁0埋めになっていますが、下の例では第4章と最後の4が重なっていたので、5桁の0埋めになっています。 できれば、 re.findallの部分を、re.subなどに置き換えたいのですが、置換後の文字列として0埋めされた文字列(4に対して004)を与える方法が良く分かりません。 d=re.sub('([\d]{1,5})',str("{0:03d}".format("\\1")),f) などと書いてみたのですが、この書式ではエラーになりました。 正しくはどのように描くべきなのでしょうか? あと、そもそもの正規表現の考え方なのですが、教えていただいた表現で改善するのは何故なのでしょうか? 確かに、'([\d]{1,2})'の方が、マッチ対象として限定されていて、厳密なチェックはできそうな気がしますが、 '(\d+?)'であっても、式が意味しているマッチ対象は同じはずです。 より、厳密な定義でないと上手く行かないのは、ライブラリの性能の問題でしょうか? それとも、正規表現を解釈するときに、あいまいな定義をした場合に不可避的についてくる論理的な問題なのでしょうか? もし、ご存知でしたら教えてください。
RiaFeed

2022/06/30 21:24

'(\d+?)'ですが、+?は最短マッチです。最短マッチは正規表現の条件を満たす中で最も文字数が短い結果を採用します(厳密には違うかも)。 この場合は数字が最低1文字あれば条件を満たすため、そのあとどれだけ数字が連続していても最短マッチの結果は数字1文字です。 ですから、(\d+?)をループさせると数字1文字ずつマッチして処理するのでその分桁数3倍という結果になっていたわけです。
MHU_ME

2022/07/01 01:18

ありがとうございます。よく理解できました。 re.subでの書き方も、よろしければ教えてください。 グループ抽出された数字を直接0埋めした文字列に置換したいのですが、第2引数の書き方で躓いています。 よろしくお願いします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問