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

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

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

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

Q&A

解決済

2回答

561閲覧

複数のフォルダからを統一したい

izuki_y

総合スコア65

Python 3.x

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

1グッド

0クリップ

投稿2023/05/03 12:33

編集2023/05/07 17:27

複数のフォルダの中の画像を一つにまとめる

ここに実現したいことを箇条書きで書いてください。

  • 複数あるフォルダ内のファイルを一つにまとめたい
  • フォルダ名の組み合わせは[アカウント名]-[開始日]-[終了日]-mediaとなっている
  • このうち、同じアカウント名のフォルダ内の画像を一つにまとめたい
  • 開始日は一番古い日時、終了日は一番新しい日時でフォルダを作りその中にファイルを入れる
  • 空フォルダは削除します
  • 同じファイル名は上書きしても問題なし

イメージ説明

前提

pythonでなシステムを作っています。日付箇所のフォルダ名が更新されない

発生している問題・エラーメッセージ

開始日、終了日のフォルダ名が更新されてない。
単純に不等号で比較しただけだと判定できないっぽい。

なんか良い方法が無いか教えて下さい

該当のソースコード

py

1#!/usr/bin/env python3 2 3import os 4import sys 5import shutil 6import glob 7 8#フォルダ内のフォルダパスを取得 9curpathDir = os.getcwd() 10folders = glob.glob(os.path.join(curpathDir, '*')) 11#print("curpath="+curpathDir) 12 13#前回フォルダ名を初期化する([アカウント名]-[開始日]-[終了日]-media) 14prevpath = ['xxxx', '9999999999999999999(999999999999999)','0000000000000000000(000000000000000)','media'] 15curpath = ['xxxx', '9999999999999999999(999999999999999)','0000000000000000000(000000000000000)','media'] 16newpath = ['xxxx', '9999999999999999999(999999999999999)','0000000000000000000(000000000000000)','media'] 17 18#for文で全部のフォルダを確認 19for folder in folders: 20 #"-"でセパレートする 21 curpath = folder.split('-') 22 23 24 #前回アカウント名と同じかを比較する 25 if bool(prevpath[0] == curpath[0]) : 26 # アカウントが同じなら現在のフォルダ→前のフォルダにファイルを移動する 27 newpath = prevpath 28 for p in os.listdir(folder): 29 print("-".join(prevpath)) 30 shutil.move(os.path.join(folder, p), "-".join(prevpath)) 31 32 #開始日を比較してを保持 33 if prevpath[1] > curpath[1]: 34 newpath[1] = curpath[1] 35 #終了日を比較して新しい方を保持 36 if prevpath[2] < curpath[2]: 37 newpath[2] = curpath[2] 38 prevpath = newpath 39 if bool(newpath != prevpath): 40 #日付に変更がある場合はフォルダ名を変更してnewpath → prevpath情報をコピー 41 os.rename(folder, "-".join(newpath)) 42 43 44 #日付に変更がない場合は何もしない 45 46 #現在のフォルダを削除する 47 os.removedirs(folder) 48 else: 49 #前回アカウント名と異なる場合は前回フォルダ名を更新して終わる 50 prevpath = curpath 51 52#終わり 53

補足情報(FW/ツールのバージョンなど)

python 3.8.4

よろしくおねがいします

tatsu99👍を押しています

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

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

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

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

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

izuki_y

2023/05/04 02:57

本編にも記載しましたが、開始日と終了日が更新されないです。 単純に不等号では無理なのかな。 zurukan2018-1532149574642860032(20220602_085819)-1536840732279209985(20220615_073918)-media zurukan2018-1539042857574891520(20220621_092945)-1540321884679831553(20220624_221209)-media zurukan2018-953201701808349184(20180116_184609)-1516946813521383425(20220421_100758)-media サンプルは上記です。 開始日と終了日の更新は諦めようかな…。
tatsu99

2023/05/04 05:12 編集

その場合、最終的に、どのようなフォルダ名のフォルダが残れば良いのですか?
tatsu99

2023/05/04 05:22

開始日の比較を行うとき、 1532149574642860032(20220602_085819)  1539042857574891520(20220621_092945) 953201701808349184(20180116_184609) を開始日としていますが、それは意図したことでしょうか。 20220602_085819 20220621_092945 20180116_184609 が開始日のようにも思えますが、如何でしょうか。
tatsu99

2023/05/04 05:25

1532149574642860032(20220602_085819) を例にとると 20220602_085819は年月日_時分秒であることは、想像できますが、 1532149574642860032は何なのでしょうか?
izuki_y

2023/05/04 12:50

返信ありがとうございます。 >1532149574642860032は何なのでしょうか? …分かりません。 ファイルを取って来る際に自動生成される値がそうなっているので自分には答えられません。 日時が新しければ新しいほど数値は増えているので単純に比較できるかと思っていたのですが どうもそんな単純ではなさそうでした。 953201701808349184(20180116_184609)とかは桁が1つ足りないなどイレギュラーなので 判定が難しいですね。 今日一日考えてみましたが、()をスプリットで抜き出して内の日時のみを判断して1532149574642860032を付けなおした方が良いのかなとは思いました。
tatsu99

2023/05/04 13:21

アカウント名は英数字でしょうか。(特殊文字%$なども含まれますか) カレントディレクトリ下には、[アカウント名]-[開始日]-[終了日]-media 形式のフォルダ だけしか 存在しないのですか。 上記形式でないフォルダとかファイルは存在しないという前提で良いのですか。
izuki_y

2023/05/04 14:12

ありがとうございます。 >アカウント名は英数字でしょうか。(特殊文字%$なども含まれますか) アカウント名はTwitterで使用できるアカウント名のため英数字のみで日本語特殊文字は使われておりません。 確認したところ、セパレートで使用している'-'もアカウント名には存在しません。 >上記形式でないフォルダとかファイルは存在しないという前提で良いのですか 存在しない前提で問題ございません。 よろしくおねがいします
tatsu99

2023/05/04 14:35

何故か、回答欄に投稿できないので、下記URLにアップしました。 https://ideone.com/GhjAjK 主な変更点は、以下の通りです。 1.比較を純粋な日付の部分のみで行うようにした。 2.リストのコピーはcopyメソッドを使用するようにした。 3.ファイルのコピー時、コピー先にファイルが存在した時、上書きするようにした。
izuki_y

2023/05/07 08:26

返信が遅くなってしまいすみません。 回答頂きましてありがとうございます。 1.比較を純粋な日付の部分のみで行うようにした。 ' if prevpath[1][-16:-1] > curpath[1][-16:-1]:'このような書き方が出来る事を初めて知りました。 tmp=prevpath[1].split('(')で分けた数値のtmp[1]を比較したものを作っていたので 後方から見て‐1文字~-16文字を比較対象とする方法は大変勉強になりました。 2.リストのコピーはcopyメソッドを使用するようにした。 ここは最初見た時はcopyを行う意味が理解できず、list.copyを行う意味を調べました。 調べた結果、代入しただけだとidは同じになるため、これらは同じリストを参照していることになり片方の値を変えると片方の値も変更されるためcopyを使って別のidにした事を理解しました。 3.ファイルのコピー時、コピー先にファイルが存在した時、上書きするようにした。 basep = os.path.basename(p) shutil.move(os.path.join(folder, p), "-".join(prevpath)+os.sep+basep) os.path.basename(p)はファイル名のみを抜き出す os.sepはpathで使われるセパレータの追加(セパレータはOSによって異なる事があるため) と言う事ですね。 頂いたソースに対して、自分のソースとの差分を確認し自分なりに理解いたしました。 本当にありがとうございます。
guest

回答2

0

ベストアンサー

回答欄に投稿できるようになったので、こちらもにアップします。

python3

1#!/usr/bin/env python3 2 3import os 4import sys 5import shutil 6import glob 7import copy 8#フォルダ内のフォルダパスを取得 9curpathDir = os.getcwd() 10folders = glob.glob(os.path.join(curpathDir, '*')) 11#print("curpath="+curpathDir) 12 13#前回フォルダ名を初期化する([アカウント名]-[開始日]-[終了日]-media) 14prevpath = ['xxxx', '9999999999999999999(999999999999999)','0000000000000000000(000000000000000)','media'] 15curpath = ['xxxx', '9999999999999999999(999999999999999)','0000000000000000000(000000000000000)','media'] 16newpath = ['xxxx', '9999999999999999999(999999999999999)','0000000000000000000(000000000000000)','media'] 17 18#for文で全部のフォルダを確認 19for folder in folders: 20 21 #"-"でセパレートする 22 curpath = folder.split('-') 23 24 25 #前回アカウント名と同じかを比較する 26 if bool(prevpath[0] == curpath[0]) : 27 # アカウントが同じなら現在のフォルダ→前のフォルダにファイルを移動する 28 newpath = prevpath.copy() 29 for p in os.listdir(folder): 30 basep = os.path.basename(p) 31 shutil.move(os.path.join(folder, p), "-".join(prevpath)+os.sep+basep) 32 33 #開始日を比較してを保持 34 if prevpath[1][-16:-1] > curpath[1][-16:-1]: 35 newpath[1] = curpath[1] 36 #終了日を比較して新しい方を保持 37 if prevpath[2][-16:-1] < curpath[2][-16:-1]: 38 newpath[2] = curpath[2] 39 40 #現在のフォルダを削除する 41 os.removedirs(folder) 42 43 if bool(newpath != prevpath): 44 #日付に変更がある場合はフォルダ名を変更してnewpath → prevpath情報をコピー 45 os.rename("-".join(prevpath), "-".join(newpath)) 46 47 #日付に変更がない場合は何もしない 48 49 prevpath = newpath.copy() 50 51 else: 52 #前回アカウント名と異なる場合は前回フォルダ名を更新して終わる 53 prevpath = curpath.copy() 54 55#終わり 56

投稿2023/05/07 08:27

tatsu99

総合スコア5424

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

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

0

shutil.moveの引数はファイル名です。*はファイル名に使えない文字だというのがエラーメッセージの意味です。

*のようなワイルドカードを使えばまとめて移動してくれるのではないかと思ったのでしょうけど、そんな機能は無いので、1ファイルずつ移動しましょう。
別案としては、*をワイルドカードとして扱ってくれる外部コマンドを呼び出す方法もありますが。

投稿2023/05/03 15:23

otn

総合スコア84423

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

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

izuki_y

2023/05/04 01:27

なるほどワイルドカードは使えないのですね。 for p in os.listdir(folder): shutil.move(os.path.join(folder, p), "-".join(prev)) でフォルダの中身を移動させるように修正しました。 ありがとうございます。
otn

2023/05/04 04:08 編集

WindowsもUnix/Linuxも、ファイル処理のシステムコールのレベルではワイルドカードなどの概念は無いので、呼び出し側でなんとかします。 ・Unix/Linux由来のシェルのコマンドラインからの起動ならシェルがコマンドラインを解析して、ワイルドカードを展開後のファイル名一覧をコマンド引数に引き渡す。 ・Windows固有のシェル(コマンドプロンプトやPowershell)のコマンドラインからの起動ならシェルに上記の機能は無いので、Unix/Linux起源の言語なら初期処理でコマンドラインを解析して、引数配列にUnix/Linuxのシェルから起動された形式互換でセット。Pythonは何故かそうしない。Windows独自言語はよく知りません。 ・コマンドラインでのワイルドカード指定じゃなくて、プログラム内でワイルドカードの処理をしたい場合はglob相当の関数があればそれで。無ければファイル一覧を取得して自分で抽出するコードを書かねば。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問