アメリカ風の日付が付いたファイルをヨーロッパ風の日付に変更

6494 ワード

あなたのボスが千以上のファイルを電子メールで送ったと仮定します.ファイル名にはアメリカ風の日付(MM-DD-YYYYY)が含まれており、ヨーロッパ風の日付(DD-MM-YYYYY)に名前を変更する必要があります.このつまらない任務を手作業で完成するには数日かかるかもしれません.プログラムを書いて完成させましょう.次に、プログラムが行うことです.•現在の作業ディレクトリのすべてのファイル名をチェックし、アメリカ風の日付を探します.•見つかったら、このファイルを名前を変えて、月と日付の位置を交換して、ヨーロッパ風にします.これは、コードが次のことをする必要があることを意味します.•アメリカ風の日付のテキストパターンを識別する正規表現を作成します.•OSを呼び出す.Listdir()を使用して、作業ディレクトリ内のすべてのファイルを見つけます.•各ファイル名をループし、正規表現で日付が含まれているかどうかを確認します.•日付が含まれている場合はshutilを使用します.move()はこのファイルに名前を変更します.このアイテムについて、新しいファイルエディタウィンドウを開き、コードをrenameDatesとして保存します.py.
アメリカ風の日付に正規表現を作成
プログラムの第1部では、必要なモジュールをインポートし、MM-DD-YYYY形式の日付を識別する正規表現を作成する必要があります.TODOコメントは、このプログラムに何を書くかを注意します.TODOとして、IDLEのCtrl-F検索機能を利用して簡単に見つけることができます.コードをこのように見せます.
#! python3
# renameDates.py - Renames filenames with American MM-DD-YYYY date format
# to European DD-MM-YYYY.

import shutil, os, re

# Create a regex that matches files with the American date format.
datePattern = re.compile(r"""^(.*?) # all text before the data
	((0|1)?\d)-					# one or two digits for the month
	((0|1|2|3)?\d)-				# one or two digits for the day
	((19|20)\d\d)				# four digits for the year
	(.#?)$						# all text after the date
	""", re.VERBOSE)

# TODO: Loop over the files in the working directory.

# TODO: Skip files without a date.

# TODO: Get the different parts of the filename.	

# TODO: Form the European-style filename.

# TODO: Get the full, absolute file paths.

# TODO: Rename the files.

知ってるよmove()関数は、ファイルの名前を変更するために使用できます.パラメータは、名前を変更するファイル名と、新しいファイル名です.この関数はshutilモジュールに存在するため、モジュールをインポートする必要があります.これらのファイルに名前を変更する前に、名前を変更するファイルを特定する必要があります.ファイル名にspam 4-4-1984が含まれている場合.txtと01-03-2014 eggs.zipのような日付は名前を変更すべきで、ファイル名には日付が含まれていないものは無視すべきです.例えばlittlebrother.epub.このモードは正規表現で識別できます.reモジュールのインポートを開始すると、reが呼び出される.compile()Regexオブジェクトを作成します.転送re.VERBOSEは2番目のパラメータとして使用され、正規表現文字列に空白文字と注釈を許可し、より読み取り可能にします.正規表現文字列は^(.*?)最初に、ファイル名の先頭、日付が表示される前のテキストと一致します.((0|1)?d)月にグループ化する.最初の数字は0または1であることができるので、正規表現は12に一致し、12月分として02にも一致し、2月としても一致します.この数字もオプションなので、4月は04か4になります.日付のグループは((0|1|2|3)?d)、類似の論理に従います.3、03、31は有効な日付数です(はい、この正規表現は4-31-2014、2-29-2013、0-15-2014などの無効な日付を受け入れます.日付には多くの特例があり、漏れやすいです.簡単にするために、このプログラムの正規表現は十分です).1885は有効な年ですが、20世紀と21世紀の年だけを探しているかもしれません.これにより、プログラムが10-10-1000のような日付以外のファイル名に誤って一致することを防止する.txt.正規表現(.*?)$を選択します.
ファイル名の日付セクションの識別
次に、プログラムはosをループする.listdir()が返すファイル名文字列のリストは、この正規表現で一致します.ファイル名に日付が含まれていないファイルは無視されます.ファイル名に日付が含まれている場合、一致するテキストはいくつかの変数に保存されます.プログラムの最初の3つのTODOの代わりに、次のコードを使用します.
#! python3
# renameDates.py - Renames filenames with American MM-DD-YYYY date format
# to European DD-MM-YYYY.

--snip--

# Loop over the files in the working directory.
for amerFilename in os.listdir('.'):
	mo = datePattern.search(amerFilename)

	# Skip files without a date.
	if mo == None:
		continue

	# Get the different parts of the filename.	
	beforePart = mo.group(1)
	monthPart = mo.group(2)
	dayPart = mo.group(4)
	yearPart = mo.group(6)
	afterPart = mo.group(8)

--snip--

search()メソッドで返されるMatchオブジェクトがNoneの場合、amerFilenameのファイル名は正規表現に一致しません.continue文は、ループの残りの部分をスキップし、次のファイル名に移行します.そうでない場合、この正規表現は一致する異なる文字列をグループ化し、beforePart、monthPart、dayPart、yearPart、afterParという変数に保存されます.これらの変数の文字列は、ヨーロッパ風のファイル名を構成するために次のステップで使用されます.グループ番号を直感的に表示するには、正規表現を最初から読んで、左かっこに遭遇するたびに1をカウントします.コードを考慮せずに、正規表現のフレームワークを書くだけです.これにより、グループ化が直感的になります.たとえば、次のようになります.
datePattern = re.compile(r"""^(1)     # all text before the data
	(2 (3) )-					      # one or two digits for the month
	(4 (5) )-				          # one or two digits for the day
	(6 (7))				              # four digits for the year
	(8)$						      # all text after the date
	""", re.VERBOSE)

ここで、番号1〜8は、正規表現のグループを表す.かっことグループ番号のみを含む正規表現のフレームを書き出します.これにより、書かれた正規表現をより明確に理解し、プログラムの残りの部分に移行します.
新しいファイル名を構成し、ファイルに名前を変更します.
最後のステップとして、前のステップで生成された変数の文字列を接続し、ヨーロッパ風の日付を取得します.日付は月より前です.プログラムの最後の3つのTODOを次のコードで置き換えます.
#! python3
# renameDates.py - Renames filenames with American MM-DD-YYYY date format
# to European DD-MM-YYYY

--snip--

	# Form the European-style filename.
	euroFilename = beforePart + dayPart + '-' + monthPart + '-'\
					+ yearPart + afterPart

	# Get the full, absolute file paths.
	absWorkingDir = os.path.abspath('.')
	amerFilename = os.path.join(absWorkingDir, amerFilename)
	euroFilename = os.path.join(absWorkingDir, euroFilename)

	# Rename the files.
	print('Renaming "%s" to "%s"...' % (amerFilename, euroFilename))
	# shutil.move(amerFilename, euroFilename) # uncomment after testing

接続された文字列をeuroFilenameという変数に保存します.次に、amerFilenameの元のファイル名と新しいeuroFilename変数をshutilに渡す.move()関数で、ファイルを名前変更します.このプログラムはmove()はコメントを呼び出し、代わりに名前を変更するファイル名を印刷します.このようにプログラムを実行すると、ファイルの名前が正しいことを確認できます.次にshutilをキャンセルする.move()で呼び出されたコメントは、プログラムを再実行し、これらのファイルを確かに名前を変更します.
類似プログラムの考え方
他にも多くの理由があり、大量のファイルに名前を変更する必要があります.•spam_の追加など、ファイル名に接頭辞を追加します.eggs.txt名前をspam_に変更eggs.txt. • ヨーロッパ風日付のファイルをアメリカ風日付に変更します.•spam 0042のようなファイル名の0を削除する.txt.
完全なコード:
#! python3
# renameDates.py - Renames filenames with American MM-DD-YYYY date format
# to European DD-MM-YYYY.

import shutil, os, re

# Create a regex that matches files with the American date format.
datePattern = re.compile(r"""^(.*?) # all text before the data
	((0|1)?\d)-					# one or two digits for the month
	((0|1|2|3)?\d)-				# one or two digits for the day
	((19|20)\d\d)				# four digits for the year
	(.#?)$						# all text after the date
	""", re.VERBOSE)

# Loop over the files in the working directory.
for amerFilename in os.listdir('.'):
	mo = datePattern.search(amerFilename)

	# Skip files without a date.
	if mo == None:
		continue

	# Get the different parts of the filename.	
	beforePart = mo.group(1)
	monthPart = mo.group(2)
	dayPart = mo.group(4)
	yearPart = mo.group(6)
	afterPart = mo.group(8)

	# Form the European-style filename.
	euroFilename = beforePart + dayPart + '-' + monthPart + '-'\
					+ yearPart + afterPart

	# Get the full, absolute file paths.
	absWorkingDir = os.path.abspath('.')
	amerFilename = os.path.join(absWorkingDir, amerFilename)
	euroFilename = os.path.join(absWorkingDir, euroFilename)

	# Rename the files.
	print('Renaming "%s" to "%s"...' % (amerFilename, euroFilename))
	# shutil.move(amerFilename, euroFilename) # uncomment after testing