✉️

PowerShell:emlのファイル名を日時_メール件名に一括リネームする

2021/04/10に公開
6

需要が限定的ですが、作成要望があったので、システムから出力される大量のemlファイルのファイル名を日時_メール件名に一括でリネームするPowerShellを書いてみた。

スクリプトの内容

  1. 禁止文字の削除用Functionを作成
    ※メールの件名にはファイル名に使用できない文字列があるので、その対策。
  2. フォルダ選択ダイアログ表示して、フォルダを選択
  3. emlファイルのプロパティから件名を取得
  4. emlファイル内のヘッダーにあるDate行から作成日時を取得
  5. 作成日時+件名でファイル名を置換

完成したスクリプト

eml_rename.ps1.
#-----------------------------------------------------------------------------
# 禁止文字の削除用Function作成
Function Remove-InvalidFileNameChars {
	param(
	  [Parameter(Mandatory=$true,
		Position=0,
		ValueFromPipeline=$true,
		ValueFromPipelineByPropertyName=$true)]
	  [String]$Name
	)

	$invalidChars = [IO.Path]::GetInvalidFileNameChars() -join ''
	$re = "[{0}]" -f [RegEx]::Escape($invalidChars)
	return ($Name -replace $re)
  }

#-----------------------------------------------------------------------------

# 置換処理開始
# フォルダ選択ダイアログ表示
Add-Type -AssemblyName System.Windows.Forms
$FolderBrowser = New-Object System.Windows.Forms.FolderBrowserDialog -Property @{ 
    RootFolder = "Desktop"
    Description = 'emlがあるフォルダを選択してください~'
}

# フォルダ選択の有無を判定
if($FolderBrowser.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK){

	## 選択したファルダパスの格納
	$path = $FolderBrowser.SelectedPath

	## WSHのShellオブジェクトを生成
	$shell=New-Object -Com Shell.Application;

	## 指定されたパス配下のファイルを全て取得(子フォルダ内のファイルも取得するよ)
	$target = Get-ChildItem $path -recurse | Where-Object {-not $_.PSIsContainer}

	## ファイル分だけ繰り返し変数に格納
	$target | ForEach-Object {

		## 拡張子判定(emlを判定)
		if($_.Extension -eq ".eml"){

			## GetDetailsOfに必要なオブジェクト
			$folderobj = $shell.NameSpace($_.DirectoryName)
			$item = $folderobj.ParseName($_.name)

			## ファイルのプロパティ値を取得 [22]は件名
			$title = $folderobj.GetDetailsOf($item,22)

			## 受信日時を取得
			## emlのヘッダーを取得(5行目から100行目)
			## Dateを含む行が取得できればOKなので、環境に応じて変更
			$GetEml = (Get-Content $_.FullName)[5..100]

			## Dateを含む行を取得して、matchesにReTimeプロパティを付与して、日付時刻を切り出し
			foreach ( $Line in $GetEml){
				if( $Line -match "Date: (?<ReTime>.* )"){
					break
				}
			}
			## datetime型に変化後、「20200101_120000」の形式に変換
			$date = ([datetime]$matches.ReTime).ToString("yyyyMMdd_HHmmss")

			if($title -eq ""){
				# ファイル名を受信日時と無題にする
				$newName = $date + "_無題" + $_.Extension

				Rename-Item $_.FullName -NewName $newName

				}else {
				# 禁止文字削除
				$ReName = Remove-InvalidFileNameChars $title
				# ファイル名を受信日時と件名にする
				$newName = $date + "_" + $ReName + $_.Extension

				Rename-Item $_.FullName -NewName $newName
				}
			}
	}
}else{
}

関連スクリプト

https://zenn.dev/8chikuwa3/articles/9989804a884492
https://zenn.dev/8chikuwa3/articles/5718421d92f745
https://zenn.dev/8chikuwa3/articles/fe548b14abd168

Discussion

ウマヤスウマヤス

はちくわ様

突然のご連絡失礼いたします。
ウマヤスと申します。
今回は御礼とご依頼があり、ご連絡いたしました。

業務でメールを整理する必要が生まれ、何か良い方法がないか?と検索したところ、このスクリプトを発見しました。まさに私が欲していたものです。スクリプトの公開ありがとうございます。

現在は私的利用の範囲内で使用しています。このスクリプトを編集・加工し、私が所属する組織内で使用する許諾を以下の内容でいただけないでしょうか。

スクリプトの使用に際して、発生したあらゆる事象の責任は使用者が負います。また、引用元であるこのページのURL及び作者名義(はちくわ様)を明記します。商業利用もいたしません。

お忙しいところ恐縮ですが、許諾の可否についてご回答お願いいたします。

はちくわはちくわ

ご連絡ありがとうございます。
こんなスクリプトでもお役に立てているのようで、嬉しく思います。

特に利用制限は考えていないため、使用者の責任の範囲内であれば、ウマヤス様の組織内で利用していただいて構いません。

ウマヤスウマヤス

ご回答ありがとうございます。

非常に助かります。
私はプログラムの知識はほぼゼロなので、ゼロベースからスクリプトを書くのは不可能でした。
このスクリプトのおかげで業務の効率が向上しました。

今後ともよろしくお願いいたします。

nonakinonaki

はちくわ様
ご教授お願いしたく、こちらへ書き込みいたしております。
私もメール1通ずつネーム変更していたので、一括で出来ないものか?とネットで調べてるところで、こちらのスクリプトを拝見し、何とか環境下で使用できるところまで漕ぎつきました。
ただ私の環境下では日時の取得がうまくいかず、今は日付-件名へのリネームを試みています。

"yyyymmdd-hhmm"部分を「yyyyMMdd」に書き換えて動作確認しておりますが
処理はうまくいっていますが、時間の部分を消してるため、エラーメッセージが出ます。
時間の部分を省く方法、どの部分からどの部分を省略するとよいのか教えていただけませんでしょうか?
お忙しいとは存じますが、何卒ご対応いただけますよう宜しくお願い致します。

はちくわはちくわ

ご連絡ありがとうございます。
不具合があったので、スクリプトを少しだけ修正しております。

日時の取得は、emlファイルのヘッダー部分を見て行ってます。

$GetEml = (Get-Content $_.FullName)[5..100]

ここでemlファイルの5行目から100行目まで見て、Date行を確認してます。
100行目までの間にDateがないと日時の取得ができないので、環境に応じて修正してください。
※emlファイルをメモ帳等で開くと確認ができます。

日時のフォーマットはここで指定しているので、ここを変更するのみになります。

- $date = ([datetime]$matches.ReTime).ToString("yyyyMMdd_HHmmss")
+ $date = ([datetime]$matches.ReTime).ToString("yyyyMMdd")

ただし、同じ日に同じ件名のメールがあるとファイル名の重複エラーになってしまうため、日時まで含めた方がエラーが起きにくいかなと思います。

nonakinonaki

早々の返信ありがとうございます。
修正、わたくしの方の環境に適したスクリプトも載せていただきありがとうございます。

日時については、はちくわ様のおっしゃる通り、先方の送信日付・時間が分かった方が、
後日メール閲覧時検索しやすいと思っております。

私の環境下で私の分かる範囲、ネットで調べた限り試行錯誤した結果、
スクリプトをあまり扱わず[HHmmss]を外した方が日付違いが起きませんでしたので、
それで行こうと思ったのですが私以外の方が使用した場合、エラーメッセージで戸惑われ
一通一通開いてファイル名変更することになると思い、無礼覚悟でコメントさせていただきました。

このスクリプトの活用で、毎日数時間やっても終わらず溜まっていくリネーム作業が
数分で終わる見込みなので、リネームを担当する者の負担軽減にもなるので、大変ありがたく思います。