2025年7月3日木曜日

【初心者向け】バッチファイルで不要なファイルを自動削除する方法

【初心者向け】バッチファイルで不要なファイルを自動削除する方法【Windows対応・安全設計】

先日でべそさんが動画編集中に誤ってピークファイルを消したようです。ある程度溜まってから手動から消していたそうで、人為的なミスだったようです。

こんな時、「不要なフォルダ内のファイルを自動で削除できたらいいな…」と思った方もいるかと思います。

そんな時、batファイルというプログラムを作ればフォルダ内のファイルを自動で削除できます。

この記事では、初心者でも簡単に自動でファイルを削除するプログラムを作る方法を教えます!

⚠️最初にお読みください|自動削除は便利ですが危険もあります

この記事で紹介する内容は、フォルダ内のファイルを自動で削除する方法です。

一度削除されたファイルは、復元が難しい可能性があります。必ず以下の点を守ってください。

  • 📦 大切なデータは削除前にバックアップを取りましょう
  • 🧪 必ずテスト用フォルダで動作確認してから本番に使いましょう
  • ❗ 誤ったフォルダを指定すると、重要なデータが消えてしまう危険があります

✅この記事でわかること

  • バッチファイル(.bat)を使って、フォルダ内の不要ファイルを自動で削除する方法
  • 特定の拡張子だけを削除する応用テクニック
  • 削除処理を誤って実行しないための安全な設計

🎒準備するもの

  • Windowsパソコン(Windows 10 または 11)
  • 不要ファイルが入っているテスト用フォルダ(例:C:\TESTT)

📝ステップ1|メモ帳でバッチファイルを作成しよう

まずは「削除プログラム」のもとになるファイルを作成します。

  1. メモ帳を開きましょう
    「スタート」→「メモ帳」と検索して開きます。
  2. 以下のコードをコピーして貼り付けてください。

✅ 基本の削除コード(サブフォルダは含みません)

@echo off
chcp 65001 >nul
setlocal

:: フォルダのパスを指定(例:C:\TESTT)
set "targetPath=C:\TESTT"

echo ============================================
echo ※以下のフォルダ内のファイルを削除します※
echo %targetPath%
echo ============================================

echo 続行しますか? (Y/N)
choice /c YN /n /m "選択してください: "
if errorlevel 2 goto :eof

echo ファイルを削除中...

:: サブフォルダを含めずに削除
forfiles /p "%targetPath%" /m *.* /c "cmd /c del /f @path"

echo ファイルの削除が完了しました。
pause

🔄 応用編|特定のファイルだけ削除したいとき

forfiles /p "%targetPath%" /m *.tmp /c "cmd /c del /f @path"

💡補足:
targetPathの値は自分の削除したいフォルダのパスに変更してください。フォルダ名にスペースが含まれていてもダブルクォーテーションで囲まれているので問題ありません。

💾ステップ2|バッチファイルとして保存する

メモ帳のメニューから「ファイル」→「名前を付けて保存」を選択します。

  • ファイル名を delete.bat にします(拡張子 .bat を忘れずに)
  • 「ファイルの種類」を「すべてのファイル」にして保存
  

🧪ステップ3|動作確認を行う

テスト用のフォルダ(例:C:\TESTT)に削除してもいいファイルをいくつか入れます。

  実行前のフォルダの様子

作成した delete.bat を右クリック →「管理者として実行」(推奨)します。

実行直後の画面

「Y」を入力すると削除が始まります。

  

実行するとフォルダの中身は全て削除されています!

  実行後のフォルダの様子

🔄 応用編|特定のファイルだけ削除したいとき

例:.tmpファイルだけ削除したい場合

forfiles /p "%targetPath%" /m *.tmp /c "cmd /c del /f @path"

他にも .log.bak など、拡張子ごとに分けて削除することができます。

💡さらに便利に|定期実行したい場合

Windowsの「タスクスケジューラ」を使えば、作成した .bat ファイルを毎週・毎日など自動で実行できます。

⚠ タスクスケジューラの設定は別記事で詳しく解説予定です。

✅まとめ|バッチファイルでPCの整理を自動化しよう

バッチファイルを使えば、クリック1つでフォルダの整理が可能です。ただし、削除系の処理には常に注意が必要です。

以下のポイントを守って、便利に・安全に使いましょう!

  • 🔄 テスト環境で必ず動作確認
  • 💾 重要ファイルはバックアップを取る
  • ✅ フォルダ指定は間違いなく慎重に

📝補足・注意

この記事の内容は自己責任で使用してください。万が一データ損失が発生しても、筆者・当サイトでは責任を負いかねます。

2025年5月3日土曜日

【無料で簡単】予約管理Webツールの作り方

【無料で簡単】Excel不要!あらゆる業種に使える「予約管理Webツール」の作り方

💭こんな悩み、ありませんか?

  • Excelでの予約管理が煩雑で、入力ミスや更新漏れが起きる
  • Googleフォームや有料予約システムは導入が難しい、または高い
  • 電話や紙での予約管理が非効率で、スタッフ間で情報が共有できない

👨‍⚕️実際の現場からー

クリニック勤務の裏方の友人は、こんな悩みを抱えていました:

  • 「先生がExcelで予約表を作っているけど、セルを探して名前を入力するのが面倒で…」
  • 「電話が鳴るたびにパソコンを開いて、間違えずに書き込むのが大変です」
  • 「Web上で簡単に予約できて、そのままExcelみたいに使えるといいんだけどなぁ…」
  • 「そもそもExcelって入れるのに1万円ぐらいかかっちゃうんだよね…」

「Excelだと不便。そもそも入れると高い。でも高機能なツールは不要」という中小規模の現場には、シンプルで無料な予約管理ツールが求められています。

✅この記事を読むとできること

  • Excel不要!Webブラウザで予約管理ができるシンプルなシステムを自作できます
  • PowerShellとHTMLだけで完結。インターネット接続も不要
  • 整骨院、美容室、学習塾、カフェ、ジムなど、業種問わず活用可能

こんな感じの予約表ができます!

🧑‍🔧ステップ1: PowerShellで予約用CSVを自動生成

以下のPowerShellスクリプトを使って、日付・時間スロット入りのCSVを作成します。


Add-Type -AssemblyName System.Windows.Forms

# フォーム作成
$form = New-Object System.Windows.Forms.Form
$form.Text = "日付選択フォーム"
$form.Width = 300
$form.Height = 220
$form.StartPosition = "CenterScreen"

# 開始日ラベル
$labelStart = New-Object System.Windows.Forms.Label
$labelStart.Text = "開始日:"
$labelStart.Top = 20
$labelStart.Left = 10
$form.Controls.Add($labelStart)

# 開始日ピッカー
$startPicker = New-Object System.Windows.Forms.DateTimePicker
$startPicker.Format = 'Short'
$startPicker.Top = 40
$startPicker.Left = 10
$form.Controls.Add($startPicker)

# 終了日ラベル
$labelEnd = New-Object System.Windows.Forms.Label
$labelEnd.Text = "終了日:"
$labelEnd.Top = 80
$labelEnd.Left = 10
$form.Controls.Add($labelEnd)

# 終了日ピッカー
$endPicker = New-Object System.Windows.Forms.DateTimePicker
$endPicker.Format = 'Short'
$endPicker.Top = 100
$endPicker.Left = 10
$form.Controls.Add($endPicker)

# OKボタン
$okButton = New-Object System.Windows.Forms.Button
$okButton.Text = "OK"
$okButton.Top = 140
$okButton.Left = 100
$okButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $okButton
$form.Controls.Add($okButton)

# フォーム表示と戻り値確認
if ($form.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {
    # 値の取得
    $start = $startPicker.Value.Date
    $end = $endPicker.Value.Date

    # 出力ファイルパス
    $outputPath = "C:\TEST\data.csv"

    # CSVヘッダー
    "予約日,予約時間,予約者1,予約者2,予約者3,予約者4,予約者5" | Out-File -FilePath $outputPath -Encoding UTF8

    # 日付ループ
    while ($start -le $end) {
        for ($hour = 9; $hour -le 21; $hour++) {
            foreach ($min in @(0, 30)) {
                $time = "{0}:{1:00}" -f $hour, $min
                "$($start.ToString('yyyy/M/d')),$time,,,,," | Out-File -Append -FilePath $outputPath -Encoding UTF8
            }
        }
        $start = $start.AddDays(1)
    }

    Write-Host "CSVファイルを作成しました: $outputPath"
} else {
    Write-Host "キャンセルされました。"
}

}

このPowerShellスクリプトを実行してみると、いつからいつまでの予約表を作るか聞かれます!

今回は開始日を2025/4/1、終了日を2025/4/30とします。

なお日付右側のボタンでカレンダーから日付を選ぶことができます。

プログラムを実行すると以下のように空のCSVファイルができます。

💻ステップ2:予約をブラウザ上で管理できるHTMLを作成

先ほどのCSVを読み込み、Web上で予約を閲覧・入力・削除できるページをPowerShellで自動生成します。
下記のコードを実行してください。

$folderPath = "C:\TEST" は便宜上の設定です。Webページで更新した後のファイルは download フォルダに保存されるため、そちらを指定しても構いません。

createhtml.ps1


# PowerShellスクリプト: reserve*.csvの最新ファイルからHTMLを生成
# ファイルパス
$folderPath = "C:\TEST"
$htmlPath = "C:\TEST\reservation.html"

# デバッグ: スクリプト開始
Write-Host "スクリプトを開始します..."

# reserve*.csvファイルの検索(最新ファイルを優先)
try {
    $csvFile = Get-ChildItem -Path "$folderPath\reserve*.csv" -File |
               Sort-Object -Property LastWriteTime -Descending |
               Select-Object -First 1
    if (-not $csvFile) {
        Write-Host "エラー: $folderPath に reserve*.csv が見つかりません。CSVファイルを準備してください。"
        Write-Host "サンプルCSVフォーマット:"
        Write-Host "予約日,予約時間,予約者1,予約者2,予約者3,予約者4,予約者5"
        Write-Host "4/1,9:00,山田,田中,,鈴木,,"
        exit
    }
    $csvPath = $csvFile.FullName
    Write-Host "最新CSVファイルを選択しました: $csvPath (更新日時: $($csvFile.LastWriteTime))"
} catch {
    Write-Host "エラー: reserve*.csv の検索に失敗しました。詳細: $_"
    exit
}

# CSV読み込み(UTF-8対応)
try {
    $csvContent = Import-Csv -Path $csvPath -Encoding UTF8
    Write-Host "CSVファイルを正常に読み込みました。レコード数: $($csvContent.Count)"
} catch {
    Write-Host "エラー: CSV読み込みに失敗しました。詳細: $_"
    Write-Host "確認事項:"
    Write-Host "- CSVファイルがUTF-8で保存されているか"
    Write-Host "- ヘッダーが正しいか(予約日,予約時間,予約者1,予約者2,予約者3,予約者4,予約者5)"
    exit
}

# CSVデータをJSONに変換
try {
    $jsonData = $csvContent | ConvertTo-Json -Compress
    Write-Host "CSVデータをJSONに変換しました。"
} catch {
    Write-Host "エラー: JSON変換に失敗しました。詳細: $_"
    exit
}

# HTMLテンプレート(変更時にreserve.csvをダウンロード)
$htmlTemplate = @"
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>オフライン予約表(CSV管理)</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; }
        table { border-collapse: collapse; width: 100%; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
        button { margin: 5px; }
        .input-group { margin-bottom: 10px; }
        label { margin-right: 10px; }
        .delete-btn { font-size: 12px; padding: 2px 5px; }
        .editable { cursor: pointer; background-color: #f9f9f9; }
        .editable:hover { background-color: #e0e0e0; }
        .alert { color: #d32f2f; font-weight: bold; margin-bottom: 10px; }
    </style>
</head>
<body>
    <h1>予約表(CSV管理)</h1>
    <div class="alert">
        予約の追加、削除、入力時にreserve.csvが自動ダウンロードされます。<br>
        ダウンロード後、C:\TEST\reserve.csvに上書き保存してください。<br>
        最新データを反映するには、PowerShellで .\generate_reservation.ps1 を再実行してください。
    </div>

    <table id="reservationTable">
        <thead>
            <tr>
                <th>予約日</th>
                <th>予約時間</th>
                <th>予約者1</th>
                <th>予約者2</th>
                <th>予約者3</th>
                <th>予約者4</th>
                <th>予約者5</th>
            </tr>
        </thead>
        <tbody id="reservationBody"></tbody>
    </table>

    <script>
        // CSVデータ(PowerShellから埋め込み)
        let reservations = $jsonData;
        console.log("初期データ:", reservations);

        // ページロード時に表を描画
        document.addEventListener("DOMContentLoaded", renderTable);

        function renderTable() {
            console.log("renderTable: 表を描画します");
            const tableBody = document.getElementById("reservationBody");
            tableBody.innerHTML = "";
            reservations.forEach((res, index) => {
                const row = document.createElement("tr");
                const formattedDate = res.予約日.includes("-")
                    ? new Date(res.予約日).toLocaleDateString("ja-JP", { month: "numeric", day: "numeric" })
                    : res.予約日;
                row.innerHTML =
                    "<td>" + formattedDate + "</td>" +
                    "<td>" + res.予約時間 + "</td>" +
                    "<td>" + (res.予約者1 && res.予約者1.trim() ? res.予約者1 + ' <button class="delete-btn" onclick="deletePerson(' + index + ', \'予約者1\')">削除</button>' : '<span class="editable" onclick="editPerson(' + index + ', \'予約者1\')">[入力]</span>') + "</td>" +
                    "<td>" + (res.予約者2 && res.予約者2.trim() ? res.予約者2 + ' <button class="delete-btn" onclick="deletePerson(' + index + ', \'予約者2\')">削除</button>' : '<span class="editable" onclick="editPerson(' + index + ', \'予約者2\')">[入力]</span>') + "</td>" +
                    "<td>" + (res.予約者3 && res.予約者3.trim() ? res.予約者3 + ' <button class="delete-btn" onclick="deletePerson(' + index + ', \'予約者3\')">削除</button>' : '<span class="editable" onclick="editPerson(' + index + ', \'予約者3\')">[入力]</span>') + "</td>" +
                    "<td>" + (res.予約者4 && res.予約者4.trim() ? res.予約者4 + ' <button class="delete-btn" onclick="deletePerson(' + index + ', \'予約者4\')">削除</button>' : '<span class="editable" onclick="editPerson(' + index + ', \'予約者4\')">[入力]</span>') + "</td>" +
                    "<td>" + (res.予約者5 && res.予約者5.trim() ? res.予約者5 + ' <button class="delete-btn" onclick="deletePerson(' + index + ', \'予約者5\')">削除</button>' : '<span class="editable" onclick="editPerson(' + index + ', \'予約者5\')">[入力]</span>') + "</td>";
                tableBody.appendChild(row);
            });
        }

        function addReservation() {
            console.log("addReservation: 予約追加を開始");
            const date = document.getElementById("date").value;
            const time = document.getElementById("time").value;
            const person1 = document.getElementById("person1").value;
            const person2 = document.getElementById("person2").value;
            const person3 = document.getElementById("person3").value;
            const person4 = document.getElementById("person4").value;
            const person5 = document.getElementById("person5").value;

            if (date && time) {
                const formattedDate = new Date(date).toLocaleDateString("ja-JP", { month: "numeric", day: "numeric" });
                reservations.push({
                    予約日: formattedDate,
                    予約時間: time,
                    予約者1: person1,
                    予約者2: person2,
                    予約者3: person3,
                    予約者4: person4,
                    予約者5: person5
                });
                console.log("addReservation: 新しい予約を追加", reservations);
                renderTable();
                saveCSV();
                document.getElementById("date").value = "";
                document.getElementById("time").value = "";
                document.getElementById("person1").value = "";
                document.getElementById("person2").value = "";
                document.getElementById("person3").value = "";
                document.getElementById("person4").value = "";
                document.getElementById("person5").value = "";
            } else {
                alert("予約日と予約時間は必須です");
            }
        }

        function deletePerson(index, personKey) {
            console.log("deletePerson: 削除開始", { index, personKey });
            reservations[index][personKey] = "";
            renderTable();
            saveCSV();
        }

        function editPerson(index, personKey) {
            console.log("editPerson: 入力開始", { index, personKey });
            const name = prompt("予約者名を入力してください");
            if (name && name.trim()) {
                reservations[index][personKey] = name.trim();
                console.log("editPerson: 名前を更新", reservations);
                renderTable();
                saveCSV();
            }
        }

        function saveCSV() {
            console.log("saveCSV: CSVダウンロードを開始");
            try {
                const header = "予約日,予約時間,予約者1,予約者2,予約者3,予約者4,予約者5\n";
                const csvContent = header + reservations.map(res =>
                    res.予約日 + "," + res.予約時間 + "," +
                    (res.予約者1 || "") + "," + (res.予約者2 || "") + "," +
                    (res.予約者3 || "") + "," + (res.予約者4 || "") + "," +
                    (res.予約者5 || "")
                ).join("\n");
                const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
                const link = document.createElement("a");
                const url = URL.createObjectURL(blob);
                link.setAttribute("href", url);
                link.setAttribute("download", "reserve.csv");
                document.body.appendChild(link);
                link.click();
                document.body.removeChild(link);
                console.log("reserve.csvをダウンロードしました。C:\\TEST\\reserve.csvに上書き保存してください。");
                console.log("saveCSV: ダウンロード完了");
            } catch (error) {
                console.error("saveCSV: エラー発生", error);
                alert("CSVダウンロードに失敗しました。コンソールを確認してください。");
            }
        }
    </script>
</body>
</html>
"@

# HTMLファイルに保存(UTF-8 BOMなし)
try {
    $htmlTemplate | Out-File -FilePath $htmlPath -Encoding UTF8
    Write-Host "HTMLファイルが正常に生成されました: $htmlPath"
    Write-Host "Microsoft Edgeで $htmlPath を開いて予約表を操作してください。"
} catch {
    Write-Host "エラー: HTMLファイルの生成に失敗しました。詳細: $_"
    exit
}

上記のコードをPowerShellで実行すると、HTMLファイルが生成されます。
ブラウザで開くと以下のような予約表が表示されます(CSVの内容を表形式で表示)。

では、予約を入れてみましょう!

  • 例: 9:00 の予約者1 に 清盛さん を登録

入力をクリックすると予約者の名前を入力するポップが出ますので皐清盛と入力します。

入力が完了すると画面上とCSVに清盛の予約が反映されます。

名前の右にある削除ボタンを押すと予約が削除され画面とCSVに反映されます。

💾ステップ3:CSVを保存・再利用して更新

予約内容を入力・削除したら、ブラウザからCSV形式で保存される仕組みになっています。保存されたCSVをPowerShellスクリプトで読み込めば、常に最新の予約表が再生成されます。

✅まとめ:Excel不要!「自分の現場向け予約管理」を自作しよう

「難しいシステムは要らないけど、紙やExcelの予約管理は限界…」

そんなあなたにぴったりなのが、PowerShellとHTMLで作るシンプルな予約管理システムです。

📌 ここまでの流れをおさらい

  • ① PowerShellでCSV予約表を自動生成
    → カレンダーで期間を選ぶだけ。30分刻みの予約枠が入ったCSVを作成。
  • ② CSVをHTMLに変換し、ブラウザで予約操作が可能に
    → 名前の入力・削除ができ、CSVとして保存されます。
  • ③ 保存したCSVで最新の予約表を再表示
    → データの再利用・更新も簡単!

システム開発の知識がなくても、導入コストゼロ・ネット不要・業種不問で使えるこの仕組み。

小さな現場にこそ、「ちょうどいい」予約管理ツールを、自分の手で作ってみませんか?