★うめじ英語塾 お問い合わせフォーム★

業務効率化!ファイルを自動で振り分けるPowerShellスクリプト

業務効率化!ファイルを自動で振り分けるPowerShellスクリプト

うめじ英語塾の梅地哲郎です。

今回は、WordExcelPDFファイルを自動的に指定のフォルダへ振り分けるPowerShellスクリプトをご紹介します。

このスクリプトを使うと、WordExcelPDFファイルを同じフォルダに入れるだけで、ファイルの種類ごとに異なる処理を行いながら、あらかじめ指定したフォルダへ自動で振り分けることができます。

このスクリプトでできること
【1】Wordファイル(.doc, .docx)を専用フォルダに移動し、読み取り専用に設定【2】Excelファイル(.xls, .xlsx, .xlsm)を専用フォルダに移動し、読み取り専用に設定

【3】PDFファイルを条件に応じて振り分け
→ ファイル名に「※メモ」が含まれる場合:「保存用」フォルダに移動
→ それ以外:「保存用」フォルダにコピー+PDF専用フォルダに移動

【4】同名ファイルがある場合は上書き確認

実は、この一連の作業は、うめじ英語塾で使うワークシートを作成したあとに行っていました。しかし、手間がかかるうえに間違いやすく、ダブルチェックが必要で、コスパの悪い作業になっていたのです。

このコードを使い始めてからは、使うたびに感動しています。なお、このブログで紹介しているコードは、ChatGPTで作成したものをClaudeでブログ用に整えたものです。フォルダー名などは、実際にわたしが使っているものから変更しています。

使い方

1. 事前準備
デスクトップに以下のフォルダを作成してください(スクリプトが自動作成もしますが、事前に作成しておくと安心です):

  • ワード用フォルダ
  • エクセル用フォルダ
  • 〇〇保存用(名前に「保存用」を含むフォルダ)

PDF用フォルダは任意の場所に作成できます(後述)。

2. スクリプトの保存
以下のコードを process.ps1 という名前で、整理したいファイルがあるフォルダに保存します。

# process.ps1
 
# ---------------------------------------------------------
# コンソールの文字コードをUTF-8に設定(日本語・特殊文字対応)
# ---------------------------------------------------------
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
 
# ---------------------------------------------------------
# 監視フォルダ = このスクリプトが置いてあるフォルダ
# ---------------------------------------------------------
$watchFolder = $PSScriptRoot
 
# ---------------------------------------------------------
# デスクトップパスを取得
# ---------------------------------------------------------
$desktopPath = [Environment]::GetFolderPath("Desktop")
 
# ---------------------------------------------------------
# Word・Excel移動先(デスクトップ基準の相対パス)
# ---------------------------------------------------------
$wordFolder = Join-Path $desktopPath "ワード用フォルダ"
$excelFolder = Join-Path $desktopPath "エクセル用フォルダ"
 
# ---------------------------------------------------------
# PDF移動先(絶対パスで指定)
# 必要に応じて変更してください
# 例: "D:\Documents\PDF" や "C:\Users\YourName\OneDrive\PDF" など
# ---------------------------------------------------------
$pdfFolder = "C:\PDF用フォルダ"
 
# ---------------------------------------------------------
# デスクトップ上で「保存用」を含む最初のフォルダを探す
# ---------------------------------------------------------
$hozonyou = Get-ChildItem -Path $desktopPath -Directory |
    Where-Object { $_.Name -like "*保存用*" } |
    Select-Object -First 1
 
if (-not $hozonyou) {
    Write-Host "デスクトップに「保存用」を含むフォルダが見つかりませんでした。処理を終了します。"
    exit
}
$hozonyouPath = $hozonyou.FullName
 
# ---------------------------------------------------------
# Word・Excel・PDFフォルダがなければ作成
# ---------------------------------------------------------
foreach ($f in @($wordFolder, $excelFolder, $pdfFolder)) {
    if (-not (Test-Path $f)) { New-Item -ItemType Directory -Path $f | Out-Null }
}
 
# ---------------------------------------------------------
# 同名ファイルがあった場合の上書き確認関数
# ---------------------------------------------------------
function Confirm-Overwrite {
    param (
        [string]$filePath
    )
    
    if (Test-Path $filePath) {
        $confirmation = Read-Host "ファイル '$filePath' はすでに存在します。上書きしますか? (Y/N)"
        if ($confirmation -eq 'Y') {
            return $true
        } else {
            Write-Host "ファイルの上書きをキャンセルしました: $filePath"
            return $false
        }
    }
    return $true
}
 
# ---------------------------------------------------------
# Excelファイルに読み取り専用属性を追加する関数
# ---------------------------------------------------------
function Set-ReadOnlyAttribute {
    param (
        [string]$filePath
    )
 
    if (Test-Path $filePath) {
        # 読み取り専用属性を設定
        attrib +r $filePath
        Write-Host "$filePath に読み取り専用属性を設定しました"
    }
}
 
# ---------------------------------------------------------
# ファイル処理
# ---------------------------------------------------------
Get-ChildItem -Path $watchFolder -File | ForEach-Object {
 
    $file = $_
    $ext = $file.Extension.ToLower()
 
    # スクリプト自身は無視
    if ($ext -eq ".ps1") { return }
 
    switch ($ext) {
        # Word
        ".doc" {
            $dest = Join-Path $wordFolder $file.Name
            if (Confirm-Overwrite $dest) {
                Move-Item $file.FullName $dest -Force
                Set-ReadOnlyAttribute $dest
                Write-Host "Word → $dest (読み取り専用)"
            }
        }
        ".docx" {
            $dest = Join-Path $wordFolder $file.Name
            if (Confirm-Overwrite $dest) {
                Move-Item $file.FullName $dest -Force
                Set-ReadOnlyAttribute $dest
                Write-Host "Word → $dest (読み取り専用)"
            }
        }
 
        # Excel
        ".xls" {
            $dest = Join-Path $excelFolder $file.Name
            if (Confirm-Overwrite $dest) {
                Move-Item $file.FullName $dest -Force
                Set-ReadOnlyAttribute $dest
                Write-Host "Excel → $dest (読み取り専用)"
            }
        }
        ".xlsx" {
            $dest = Join-Path $excelFolder $file.Name
            if (Confirm-Overwrite $dest) {
                Move-Item $file.FullName $dest -Force
                Set-ReadOnlyAttribute $dest
                Write-Host "Excel → $dest (読み取り専用)"
            }
        }
        ".xlsm" {
            $dest = Join-Path $excelFolder $file.Name
            if (Confirm-Overwrite $dest) {
                Move-Item $file.FullName $dest -Force
                Set-ReadOnlyAttribute $dest
                Write-Host "Excel → $dest (読み取り専用)"
            }
        }
 
        # PDF
        ".pdf" {
            if ($file.Name -like "*※メモ*") {
                # メモあり → 保存用に移動
                $dest = Join-Path $hozonyouPath $file.Name
                if (Confirm-Overwrite $dest) {
                    Move-Item $file.FullName $dest -Force
                    Write-Host "PDF(メモあり) → $dest"
                }
            } else {
                # メモなし → 保存用にコピー + 指定フォルダに移動
                $copyDest = Join-Path $hozonyouPath $file.Name
                $moveDest = Join-Path $pdfFolder $file.Name
 
                if (Confirm-Overwrite $copyDest) {
                    Copy-Item $file.FullName $copyDest -Force
                    Write-Host "PDF(メモなし) コピー:$copyDest"
                }
                if (Confirm-Overwrite $moveDest) {
                    Move-Item $file.FullName $moveDest -Force
                    Write-Host "PDF(メモなし) 移動:$moveDest"
                }
            }
        }
 
        default {
            Write-Host "対象外ファイル: $($file.Name)"
        }
    }
}

3. 実行方法

  1. 整理したいファイルがあるフォルダに process.ps1 を配置
  2. PowerShellを開く(フォルダを右クリック→「PowerShellウィンドウをここで開く」)
  3. 以下のコマンドを実行:
.\process.ps1

初回実行時にセキュリティ警告が出る場合は、以下のコマンドで実行ポリシーを変更してください:

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

カスタマイズのヒント
最速で運用するには、上のメインスクリプトをChatGPTに貼り付け、ご自身のフォルダーなどを指定してカスタマイズしてもらうのがよいと思います。以下は、Claudeによる解説です。

PDF保存先を変更したい場合
スクリプト内の以下の部分を編集してください:

$pdfFolder = "C:\PDF用フォルダ"

変更例:
① デスクトップに保存する場合:

$pdfFolder = Join-Path $desktopPath "PDF用フォルダ"

Dドライブに保存する場合:

$pdfFolder = "D:\Documents\PDF"

③ OneDriveに保存する場合:

$pdfFolder = "C:\Users\YourUserName\OneDrive\PDF"

④ ネットワークドライブに保存する場合:

$pdfFolder = "\\ServerName\SharedFolder\PDF"

◆フォルダ名を変更したい場合
スクリプト内の以下の部分を編集してください:

$wordFolder = Join-Path $desktopPath "ワード用フォルダ"
$excelFolder = Join-Path $desktopPath "エクセル用フォルダ"

例:英語のフォルダ名にする場合

$wordFolder = Join-Path $desktopPath "Word"
$excelFolder = Join-Path $desktopPath "Excel"

WordExcelも絶対パスで指定したい場合
デスクトップ以外の場所に保存したい場合は、PDFと同様に絶対パスで指定できます:

$wordFolder = "D:\Documents\Word"
$excelFolder = "D:\Documents\Excel"
$pdfFolder = "D:\Documents\PDF"

◆読み取り専用設定を解除したい場合
Set-ReadOnlyAttribute $dest の行をコメントアウト(行頭に # を追加)するか、削除してください。

◆他のファイル形式にも対応させたい場合
switch 文に新しいケースを追加します。例えば、PowerPointファイルを追加する場合:

# PowerPoint移動先を定義
$pptFolder = "C:\PowerPoint用フォルダ"
 
# switch文内に追加
".ppt" {
    $dest = Join-Path $pptFolder $file.Name
    if (Confirm-Overwrite $dest) {
        Move-Item $file.FullName $dest -Force
        Write-Host "PowerPoint → $dest"
    }
}
".pptx" {
    $dest = Join-Path $pptFolder $file.Name
    if (Confirm-Overwrite $dest) {
        Move-Item $file.FullName $dest -Force
        Write-Host "PowerPoint → $dest"
    }
}

注意事項

  • ファイルは移動されるため、元のフォルダからなくなります
  • 同名ファイルがある場合は上書き確認が表示されます
  • スクリプト自身(.ps1ファイル)は処理対象外です
  • 初回実行前に、大切なファイルはバックアップを取ることをおすすめします
  • 絶対パスを使用する場合、ドライブやフォルダが存在することを確認してください

パスの書き方のポイント

  • 相対パスJoin-Path $desktopPath "フォルダ名" → デスクトップ内のフォルダ
  • 絶対パス"C:\フォルダ名" → 指定した場所に直接アクセス
  • ネットワークパス"\\サーバー名\共有フォルダ\フォルダ名" → ネットワークドライブ
  • バックスラッシュWindowsでは \ を使用します(/ ではありません)

まとめ

このスクリプトを使えば、同じフォルダーに混在する異なる種類のファイルを、一瞬で整理できます。ぜひ試してみてください!