🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

バッチファイル

バッチファイル(Batch File)は、Windowsのコマンドラインインタープリターによって複数のコマンドを実行させる事が出来るスクリプトファイルです。

正規表現

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

Python

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

Q&A

解決済

2回答

1353閲覧

バッチファイルにD&Dしたファイルをpythonで読み込み、ファイル名ごとにフォルダ分けがしたい

SILASSETH

総合スコア7

ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

バッチファイル

バッチファイル(Batch File)は、Windowsのコマンドラインインタープリターによって複数のコマンドを実行させる事が出来るスクリプトファイルです。

正規表現

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

Python

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

0グッド

0クリップ

投稿2020/01/07 08:33

前提・実現したいこと

バッチファイルにD&Dしたファイルをpythonで読み込み、ファイル名ごとにフォルダ分けがしたい

具体的には

(xxx) [yyy (zzzz)]123456.zip を D&D した際に、指定したフォルダ(D:\sagyo\aaa\yyy(zzzz)\)に ファイル名の[]内のフォルダ名の下に移動する(フォルダがなければ作成する)

C:(xxx) [yyy (zzzz)]123456.zip をバッチファイルにD&D した際に

D:\sagyo\aaa\yyy(zzzz)(xxx) [yyy (zzzz)]123456.zip

のように移動していてほしいということです。

また、ファイル名に2つの[]が現れた際(入れ子でない)は、最初の[]を採用するようにもしておきたいです。(re.searchは最初の検索結果を採用すると書いてあったので採用しています。)
例:(xxx) [yyy (zzzz)]123456[aaa].zip なら[yyy (zzzz)]を採用。

見よう見まねでコードを書いてみたのですが、どうして動かないのか分からないので、ご教授願いたいです。
正規表現は試行錯誤すれば書ける(かつ私の環境での汎用性が高くなる)ので、できれば正規表現は使いたいです。

よろしくお願い致します。

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

D:\sagyo>python zip.py "D:\sagyo(xxx) [yyy (zzzz)]123456.zip" zip.py -> D:\sagyo\aaa\None\None Traceback (most recent call last): File "C:\Users\---\AppData\Local\Programs\Python\Python37\lib\pathlib.py", line 1258, in mkdir self._accessor.mkdir(self, mode) OSError: [WinError 123] ファイル名、ディレクトリ名、またはボリューム ラベルの構文が間違っています。: "D:\sagyo\aaa\<re.Match object; span=(15, 27), match='[yyy (zzzz)]'>" During handling of the above exception, another exception occurred: Traceback (most recent call last): File "zip.py", line 14, in <module> File "C:\Users\---\AppData\Local\Programs\Python\Python37\lib\pathlib.py", line 1267, in mkdir if not exist_ok or not self.is_dir(): File "C:\Users\---\AppData\Local\Programs\Python\Python37\lib\pathlib.py", line 1358, in is_dir return S_ISDIR(self.stat().st_mode) File "C:\Users\---\AppData\Local\Programs\Python\Python37\lib\pathlib.py", line 1168, in stat return self._accessor.stat(self) OSError: [WinError 123] ファイル名、ディレクトリ名、またはボリューム ラベルの構文が間違っています。: "D:\sagyo\aaa\<re.Match object; span=(15, 27), match='[yyy (zzzz)]'>"

該当のソースコード

dos

1python zip.py %1 2timeout 100

python

1import shutil 2from pathlib import Path 3import sys 4import re 5 6output_dir = Path("D:/sagyo/aaa") # 出力ディレクトリ 7 8for path in sys.argv: 9 name = re.search(r'[.*]' , path) 10 name = str(name) 11 12 # サブディレクトリを作成する。 13 output_subdir = output_dir / name 14 output_subdir.mkdir(parents=True, exist_ok=True) 15 16 # 移動先のファイルパス 17 output_path = output_subdir / name 18 print(f"{path} -> {output_path}") 19 20 # ファイルを移動する。 21 shutil.move(path, output_path) 22 23pause

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

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

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

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

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

guest

回答2

0

ベストアンサー

テストはしてませんが、output_subdir と output_path は合っていると思います。

py

1import shutil 2from pathlib import Path 3import sys 4import re 5 6output_dir = Path("D:/sagyo/aaa") # 出力ディレクトリ 7 8for arg in sys.argv[1:]: 9 result = re.search('([.*])' , arg) 10 sub_folder = result.group(0) 11 path = Path(arg) 12 13 # サブディレクトリを作成する。 14 output_subdir = output_dir / sub_folder 15 output_subdir.mkdir(parents=True, exist_ok=True) 16 17 # 移動先のファイルパス 18 output_path = output_subdir / path.name 19 print(f"{path} -> {output_path}") 20 21 # ファイルを移動する。 22 shutil.move(path, output_path)

投稿2020/01/15 06:00

mmaeda

総合スコア269

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

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

SILASSETH

2020/01/15 06:47

無事ファイル移動が可能になりました。ありがとうございました。 補足ですが、batファイルは for %%a in (%*) do ( %~dp0\zip.py %%a echo %%a と、書き直した上で動かしました。
guest

0

必要最小限のコードにして、ちょっとずつ期待した動作になるのかを確認しながら
実装を進めることをお勧めします。

ポイントは所定の文字列がうまく抽出されるかではないでしょうか。

そもそも、re.searchの戻り値をstrでは期待通りに動作しないと思います。

python

1 2import re 3 4str = "(xxx) [yyy (zzzz)]123456[aaa].zip" 5 6name = re.search(r'[.*]' , str) 7print(name.group())

上記で確認すると、結果は以下のようになります。
[yyy (zzzz)]123456[aaa]

期待通りの結果になるためには、「python re search」などでググってみましょう。
https://note.nkmk.me/python-re-match-search-findall-etc/
*?で非貪欲マッチができるとあります。

そこで、search部分を以下のように修正します。

python

1import re 2 3str = "(xxx) [yyy (zzzz)]123456[aaa].zip" 4 5name = re.search(r'[.*?]' , str) 6print(name.group()) 7

以下のような結果となりました。
[yyy (zzzz)]

そこで、以下のようにすると、期待した文字列が取得できるようになります。

python

1name = name.group()

さらにそこからパスを生成するためには、以下のようにすることをお勧めします。

python

1import os 2 3name = name.group() 4path = os.path.join(output_dir, name)

投稿2020/01/07 10:24

t_obara

総合スコア5488

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

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

SILASSETH

2020/01/07 11:37

そのサイトは私も拝見したのですが 「マッチする部分が複数ある場合は、最初のマッチ部分のみが返される。」と書いてあったので、最初の[]がヒットするものだと勘違いしてしまいました。ご指摘ありがとうございます。 確かに最初から文字列で書けば認識されるのですが、batファイルからpathを受けて動かすと Traceback (most recent call last): File "zip.py", line 12, in <module> name = name.group() AttributeError: 'NoneType' object has no attribute 'group' で止まります……
t_obara

2020/01/08 01:33

re.search の結果がNoneになっています。その部分の修正が間違えているのではないでしょうか。
SILASSETH

2020/01/08 17:50

output_dir = Path("D:/sagyo/aaa") # 出力ディレクトリ for path in sys.argv: name = re.search(r'[.*?]' , path) name = name.group() path = os.path.join(output_dir, name) という形なのですが、noneになってしまうのは何故なのでしょうか……。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問