バッチファイルでファイル・フォルダを一括削除する（削除候補リストを外部ファイル化）

Y子です。
__[昨日の記事](https://qiita.com/koiwaiwaiko/items/08f53bb3e95c331de221 "バッチファイルで外部ファイルから1行ずつ取得する")__ を参考に、ファイルやフォルダの削除を効率的に行う方法を考えます。
ファイル名やフォルダ名を書いた外部ファイルから1行ずつ取得し、ファイルやフォルダを削除するバッチファイルを作成してみます。

https://qiita.com/koiwaiwaiko/items/08f53bb3e95c331de221

# 概要・用途
テキストファイルに、削除候補のファイルやフォルダを列挙しておきます。
これを読み込んで、削除を実行します。

たとえば、 __「複数のPCから、同じファイルを削除する」__ のような用途が考えられます。
PCやファイル数が多くなるとオペミスも発生しやすくなるので、自動化して間違いない作業を目指します。
削除の成否をコメント出力するので、これをログとして持ち帰れば作業記録にもなります。

# コード
```bat:extfile_filedel.bat
@echo off

rem 削除候補ファイルのリスト
set str_file=file_list.txt

rem ベースフォルダ
set str_dir=C:\work dir

for /f "delims= eol=" %%a in (%str_file%) do (
  rem フォルダの場合
  if exist "%str_dir%\%%a\" (
    rem フォルダ削除実行(中身も確認なく削除)
    rmdir /s /q "%str_dir%\%%a"

    if exist "%str_dir%\%%a\" (     rem まだフォルダがある
      echo ×フォルダ削除失敗（%%a）
    ) else (                        rem フォルダが削除済み
      echo ○フォルダ削除成功（%%a）
    )

  rem ファイルの場合
  ) else if exist "%str_dir%\%%a" (
    rem ファイル削除実行
    del "%str_dir%\%%a"

    if exist "%str_dir%\%%a" (      rem まだファイルがある
      echo ×ファイル削除失敗（%%a）
    ) else (                        rem ファイルが削除済み
      echo ○ファイル削除成功（%%a）
    )

  rem 存在しない場合
  ) else (
    echo 存在しません（%%a）
  )
)

pause
```

仕様はおおよそ以下の通りです。

* 「削除候補ファイルのリスト」の各行は、「ベースフォルダ」からの相対パスで書く（そうなるように、リストとベースフォルダを設定する）
* リストは、ワイルドカード（`*`）を使って書いてもよい
* ファイルもフォルダも削除可能。フォルダは中身もまるごと消す
* 削除処理前に存在を確認する。無ければ「存在しません」と表示し、削除処理をしない
* 削除処理後に存在を確認する。在れば「×削除失敗」、無ければ「○削除成功」と表示する

技術的な補足です。

* 「`if exist "%str_dir%\%%a\"`」で、「存在するかどうか」と「フォルダかどうか」を同時に確認しています。最後を「`\`」にして`true`なら、「フォルダが存在する」となります。
* フォルダを「`rmdir`」コマンドで削除します。オプションの「`/s`」は「ファイルやサブディレクトリも含めて削除する」、「`/q`」は「`/s`で削除する際に確認メッセージを表示しない」です。


```file_list.txt（削除候補ファイルのリスト）
test01.txt
test02.txt
test03.zip
test1*
dir1\test21.txt
dir1\test22.zip
dir2
```

ベースフォルダ（`C:\work dir`）の中にこのファイルやフォルダがあれば削除する、というリストです。
4行目（`test1*`）はワイルドカードです。例えば「`test10.txt`」というファイルがあれば削除します。
5～6行目は、「`dir1`」というフォルダの中にあるファイルが削除候補です。「`dir1`」フォルダ自体は削除されません。
7行目（`dir2`）は、フォルダが削除候補です。中に何が入っていようが関係なく、フォルダごと削除します。

```:実行結果1
> extfile_filedel.bat
○ファイル削除成功（test01.txt）
○ファイル削除成功（test02.txt）
存在しません（test03.zip）
○ファイル削除成功（test1*）
○ファイル削除成功（dir1\test21.txt）
存在しません（dir1\test22.zip）
○フォルダ削除成功（dir2）
続行するには何かキーを押してください . . .
```

存在しないファイルがあったものの、削除したいファイル・フォルダはすべて消えた例です。

```:実行結果2
> extfile_filedel.bat
○ファイル削除成功（test01.txt）
C:\work dir\test02.txt
プロセスはファイルにアクセスできません。別のプロセスが使用中です。
×ファイル削除失敗（test02.txt）
存在しません（test03.zip）
C:\work dir\test12.txt
プロセスはファイルにアクセスできません。別のプロセスが使用中です。
×ファイル削除失敗（test1*）
○ファイル削除成功（dir1\test21.txt）
存在しません（dir1\test22.zip）
C:\work dir\dir2\test21.txt - プロセスはファイルにアクセスできません。別のプロセスが使用中です。
×フォルダ削除失敗（dir2）
続行するには何かキーを押してください . . .
```

一部のファイルをWordで開いて削除できないようにした状態で、実行しました。

`test02.txt`が削除できなかったため、そのように表示されています。

`test12.txt`も削除できなかったため、ワイルドカードで指定したファイルの削除が失敗しました。しかし、例えば`test11.txt`は削除に成功しています。ワイルドカードは、削除できたものが記録に残らないので、注意が必要です。

`dir2/test21.txt`もWordで開いていたので、フォルダ`dir2`が削除失敗しました。しかし、例えば`dir2/test22.txt`は削除に成功しています。フォルダの中身は、削除できたものが記録に残らないので、これも注意が必要です。

```:実行結果3
> extfile_filedel.bat > log3.txt
プロセスはファイルにアクセスできません。別のプロセスが使用中です。
プロセスはファイルにアクセスできません。別のプロセスが使用中です。
C:\work dir\dir2\test21.txt - プロセスはファイルにアクセスできません。別のプロセスが使用中です。
```

```log3.txt
○ファイル削除成功（test01.txt）
C:\work dir\test02.txt
×ファイル削除失敗（test02.txt）
存在しません（test03.zip）
C:\work dir\test12.txt
×ファイル削除失敗（test1*）
○ファイル削除成功（dir1\test21.txt）
存在しません（dir1\test22.zip）
×フォルダ削除失敗（dir2）
続行するには何かキーを押してください . . . 
```

「実行結果2」と同じ条件で実行し、標準出力だけをログファイルに出力しました。
できれば、標準エラー出力もログファイルに残して、作業履歴にしたいところです。

```:実行結果4
> extfile_filedel.bat > log4.txt 2>&1
```

```log4.txt
○ファイル削除成功（test01.txt）
C:\work dir\test02.txt
プロセスはファイルにアクセスできません。別のプロセスが使用中です。
×ファイル削除失敗（test02.txt）
存在しません（test03.zip）
C:\work dir\test12.txt
プロセスはファイルにアクセスできません。別のプロセスが使用中です。
×ファイル削除失敗（test1*）
○ファイル削除成功（dir1\test21.txt）
存在しません（dir1\test22.zip）
C:\work dir\dir2\test21.txt - プロセスはファイルにアクセスできません。別のプロセスが使用中です。
×フォルダ削除失敗（dir2）
続行するには何かキーを押してください . . . 
```

「`2>&1`」で、標準エラー出力（`2`）も標準出力（`1`）と同じファイルに出力するように指定した結果、すべてが同じログファイルに記録されました。

# おわりに
例えば現地作業などでは、ファイルを持ち込むのは気軽にできても、ファイルを削除するのは緊張するものです。
自社環境で検証済みのリストを現地でも使えれば、効率よく間違いなく、不要なファイルを削除できると思います。

ではまた！