PowerShellでファイルを自動で日付ごとのフォルダに移動するには

ドラレコで録画した映像ですが。ファイル数が数千~数万個あって、手がつけられません。

PowerShellを使って、こちらを自動で整頓したいと思います。

ファイル名の日付を判別して、自動で日付のフォルダに移動してみました。

フォルダ名に曜日と祝日・休日もいれると、このような感じです。これなら、平日に運転した記録か、なにか休日に遊びに行った記録か、すぐ判別することが可能です。

方法を記録しておこうと思います。


PowerShellでファイルを日付+曜日+祝日・休日のフォルダに自動移動する手順

PowerShellの実行はISEを使用

PowerShellのスクリプトの実行は、Windows PowerShell ISEを使用しました。

OSはWindows 10ですが、標準でOSに付属しているものです。Windows 11でも付属していると思います。このような感じで、画面の上半分にスクリプトを貼って、▶ボタンで実行しました。

ではそのスクリプトについて。


PowerShellのフォルダ選択ダイアログ表示について

ファイルを整頓する対象のフォルダは、「フォルダーの参照」ダイアログボックスで選択できます。

該当のコードは、このあとご紹介するスクリプトに組み込まれていますが、詳細を知りたい場合はこちらになります。

PowerShellでフォルダーの参照ダイアログを表示するには
Windows を使用していて。 ファイルの整理など、なにか細々とした作業をするとき、今までコマンドプロンプトを使用していましたが、や...

ファイル名から日付の取り出しについて

ファイル名から日付を取り出す方法の詳細はこちらになります。こちらも後で出てくるクラスに組み込み済みです。

PowerShellで日時が入ったファイル名から年月日を取り出すには
ドライブレコーダーで録画したビデオファイルですが。 ファイル名に日時が入っています。このような感じで。 このファイル名から、日付...

日付から曜日と祝日・休日名称の判別について

ファイルを入れるフォルダですが、日付+曜日+祝日・休日の場合はその名称を付けました。

詳細はこちらになります。

PowerShellで日付に対応する曜日と祝日・休日を得るには
日付から、PowerShellにて曜日を判別する方法と。 それと「国民の祝日・休日」CSVファイルを使って、該当の日付が何の日かを判別...

この記事では、$env:TEMPフォルダに祝日・休日のCSVファイルをダウンロードします。ダウンロード済みかどうか判定しているため、2回目以降の実行は、インターネットの接続は行われません。


ファイル名の日付からフォルダに整頓するPowerShellスクリプト

以上の内容を組み合わせて、クラスを作ってみました。

# Powershell ちょっとしたファイル操作クラス
# © 2024 denor.jp
class DenorFileUtility {
    [System.Object[]] $syukujitsuCsv    # 祝日・休日CSV
    # コンストラクタ
    DenorFileUtility() {
       $this.ImportSyukujitsuCsv()  # 祝日・休日CSVファイル読み込み
    }
    # 祝日・休日CSVファイルを変数に読み込みます
    [void] ImportSyukujitsuCsv() {
        # ダウンロード済みなら終了
        if($this.syukujitsuCsv -ne $null) {
            return
        }
        # CSVファイルパス 環境変数TEMP
        $outfile = $env:TEMP + "\syukujitsu.csv"
        if ( -not (Test-Path -Path $outfile)) {
            try {
                # ファイルがなければダウンロード
                Invoke-WebRequest `
                -URI https://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv `
                -OutFile $outfile
            } catch {
                Write-Host "CSVファイルをダウンロードできませんでした。"
                Write-Host $_
                exit 
            }
        } else {
            write-verbose "CSVファイルはダウンロード済みです"
        }
        # メンバ変数へCSV読み込み
        $this.syukujitsuCsv = Import-Csv $outfile -Encoding Default
    }
    # 祝日・休日を検索します
    [string] GetSyukujitsu([datetime]$date) {
        $syukujitsu = ($this.syukujitsuCsv | Where-Object "国民の祝日・休日月日" -Match $date.ToString("yyyy/M/d"))."国民の祝日・休日名称"
        return $syukujitsu
    }
    #ドライブレコーダー録画ファイル名から日付を取り出して返します
    static [Array] GetDateByFileName([string]$filename) {
        if($filename -Match '^(?<year>\d{4})_(?<month>\d{2})(?<day>\d{2})_(?<hour>\d{2})(?<minute>\d{2})(?<sec>\d{2})' -ne $true) {
        return $null
        }
        return @{
            Year = $Matches.year
            Month = $Matches.Month
            Day = $Matches.day
            Hour = $Matches.hour
            Minute = $Matches.minute
            Sec = $Matches.sec
            }
    }
    # フォルダ選択ダイアログを表示します
    static [string] SelectFolder() {
        return [DenorFileUtility]::SelectFolder("")
    }
    # フォルダ選択ダイアログ表示
    static [string] SelectFolder([string]$InitialFolder) {
        Add-Type -AssemblyName System.windows.forms
        $dialog = New-Object -TypeName System.Windows.Forms.FolderBrowserDialog
        $dialog.rootfolder = "MyComputer"
        $dialog.SelectedPath = $InitialFolder
        if($dialog.ShowDialog() -ne "OK") {
            $selected = $null
        } else {
            $selected = $dialog.SelectedPath
        }
        Remove-Variable -Name dialog
        return $selected
    }
    # 日付+曜日+祝日休日名のフォルダ名を生成します
    [string] GetDateFolderName([System.Object[]]$filedate) {
        # 日付オブジェクト作成
        $date = Get-Date -year $filedate.year -month $filedate.month -day $filedate.day
        $foldername = $filedate.year + $filedate.month + $filedate.day + $date.ToString("ddd")
        # 祝日・休日名取得
        $syukujitsu = $this.GetSyukujitsu($date)
        if ($syukujitsu -ne "" ) {
            $foldername = $foldername + "_" + $syukujitsu
        }
        Remove-Variable -Name syukujitsu
        Remove-Variable -Name date
        return $foldername
    }
    # 選択したフォルダにあるファイル名から日付を取り出し、日付のフォルダにファイルを移動します
    [void] MoveFilesToDateFolder() {
        # フォルダ選択
        $folder = [DenorFileUtility]::SelectFolder()
        if($folder -eq "") {
            return
        }
        # フォルダ移動
        Push-Location $folder
        # ファイル一覧取得
        $files = Get-ChildItem -File
        foreach($file in $files) {
            #[System.IO.FileInfo] $file
            # 日付取り出し
            $filedate = [DenorFileUtility]::GetDateByFileName($file.Name)
            if($filedate -eq $null) { continue }
            "対象のファイル名: " + $file.Name | Write-Verbose

            # 日付からフォルダ名作成
            $foldername = $this.GetDateFolderName($filedate)
            $folderpath = ".\"+ $foldername
            if ( -not (Test-Path -Path $folderpath)) {
                "ディレクトリを作成します: " + $foldername | Write-Verbose 
                New-Item -Path ".\" -Name $foldername -ItemType "directory"
            }
            # ファイルを移動
            "ファイルを移動します: " + $folderpath | Write-Verbose 
            $file.MoveTo($folder + "\" + $folderpath + "\" + $file.Name)
        }
        Pop-Location
        Remove-Variable -Name files
        Remove-Variable -Name folder
    }
}

# 詳細表示モード有効
$VerbosePreferenceDefault = $VerbosePreference
$VerbosePreference = "continue"

# インスタンス生成
$util = [DenorFileUtility]::new()

# ファイルを日付のフォルダに移動
$util.MoveFilesToDateFolder()

# インスタンス削除
Remove-Variable -Name util
# &copy; 2024 denor.jp

こちらをWindows PowerShell ISEに貼り付けて実行すれば、前述のフォルダ選択ダイアログが表示されます。

クラスで実装した理由は、モジュールとして再利用できること・変数の管理が楽な理由からです。(クラスならnewする変数が1つだけでOK

モジュールの実装方法は、追々別の記事にて。


便利ですねPowerShell。

Windowsに付属しているということで、なにかコンパイラやランタイムのインストールは不要で、ISEを起動するだけで使用できてしまいます。

編集・実行だけではなく、F5キーでデバッグ実行までできるため、バグの修正も簡単にできます。

連休の時期のため、お車で出かけることもあるかと思います。

ドライブレコーダーの映像が溜まって、手が付けらず、放置しているのでしたら。(私だ

日付ごとにフォルダ分けするだけで、不要な映像、大切な映像の判断が、ずいぶん楽になると思います。

どんなWindows PCでも実行できますので、よろしければお試し下さい。

スポンサーリンク

フォローする

スポンサーリンク