HOWTO · Batch
バッチ スクリプトでファイルを抽出または解凍する
このチュートリアルでは、バッチ スクリプトでファイルを抽出または解凍する方法について説明します。
このページの内容
WindowsのバッチファイルからZIPアーカイブを展開するには、アーカイブと展開先のパスを設定し、コマンドラインの展開ツールを呼び出します。対応するWindows 10以降では、組み込みのtarを利用できます。7-Zipも、インストールすれば使用できます。このガイドでは各コマンドに加えて、Windows ShellとVBScriptを使う方法や、複数のアーカイブを安全に処理する方法を説明します。コマンド例はWindows向けの構文を示したもので、このパケットでは実行されていません。
WindowsのtarでZIPファイルを展開する
対応するWindows 10以降では、別のツールをインストールしなくてもtarでZIPアーカイブを展開できます。Windowsのtarコマンドとその利用可能性については、Microsoftのこちらの説明を参照してください。このバッチ例では、zipFileにC:\Work\sample.zip、outputDirにC:\Work\sample-extractedを指定しています。どちらも例示用のパスなので、自分の環境に合わせて置き換えてください。スクリプトは必要に応じて展開先を作成し、その後tar -xf "%zipFile%" -C "%outputDir%"を実行します。
-xは展開、-fはアーカイブの指定、-Cは内容を書き出すディレクトリの指定に使います。展開先ディレクトリは、存在しない場合に先に作成されます。変数を引用符で囲むことで、パスに空白があってもひとつの引数として扱えます。この例の対象はZIPアーカイブです。古いWindows環境でもtarが使えるとは限らず、このコマンドがあらゆるアーカイブ形式に適するわけでもありません。
これを.batファイルとして保存し、対応するWindows環境で実行してください。
@echo off
setlocal
set "zipFile=C:\Work\sample.zip"
set "outputDir=C:\Work\sample-extracted"
if not exist "%zipFile%" (
echo ZIP archive not found: "%zipFile%"
exit /b 1
)
if not exist "%outputDir%" (
mkdir "%outputDir%"
if errorlevel 1 (
echo Could not create destination: "%outputDir%"
exit /b 1
)
)
tar -xf "%zipFile%" -C "%outputDir%"
exit /b %errorlevel%
Python標準ライブラリを使って展開結果を試す場合は、次の自己完結型の例を実行できます。一時ディレクトリに小さなZIPアーカイブを作成して展開し、外部アーカイブや固定パスに頼らず、展開されたファイルを確認します。
from pathlib import Path
from tempfile import TemporaryDirectory
from zipfile import ZipFile
with TemporaryDirectory() as temp_dir:
root = Path(temp_dir)
archive = root / "sample.zip"
destination = root / "extracted"
destination.mkdir()
with ZipFile(archive, "w") as zip_file:
zip_file.writestr("notes/readme.txt", "Batch extraction demo")
with ZipFile(archive) as zip_file:
zip_file.extractall(destination)
assert (destination / "notes" / "readme.txt").read_text() == "Batch extraction demo"
このPython例は、入力アーカイブと展開先の関係を示すものです。Windowsのバッチコマンドではなく、どのWindowsバージョンにtarが含まれるかを示すものでもありません。上記のWindows用tarコマンドは、ここでは実行されていません。正常に実行されると、アーカイブの内容はoutputDirに指定したディレクトリに展開されます。
7-ZipでZIPファイルを展開する
7-Zipがインストールされている場合や、ZIP以外の形式にも対応する展開機能が必要な場合は、7-Zipを使います。このバッチ例では、sevenZipPathにC:\Program Files\7-Zip\7z.exe、zipFileにC:\Work\sample.zip、outputDirにC:\Work\sample-extractedを指定しています。インストール先やファイルに合わせて変更してください。コマンドとスイッチについては、7-Zip公式のコマンドライン説明を参照してください。スクリプトは必要に応じて展開先を作成し、その後"%sevenZipPath%" x "%zipFile%" -o"%outputDir%"を実行します。
xコマンドはアーカイブ内のディレクトリ構造を保って展開し、-oは展開先を指定します。例のように、-oはパスの直前に付けてください。先に7-Zipをインストールするか、sevenZipPathを実際のインストール先に合わせて変更します。展開されたファイルはoutputDirの下に置かれます。これを.batファイルとして保存してください。このWindows用コマンド例は、ここでは実行されていません。後続のバッチ処理が展開完了を前提とする場合は、成功を報告する前にコマンドの終了ステータスを確認し、アーカイブが途中までファイルを書き出している可能性も考慮してください。
@echo off
setlocal
set "sevenZipPath=C:\Program Files\7-Zip\7z.exe"
set "zipFile=C:\Work\sample.zip"
set "outputDir=C:\Work\sample-extracted"
if not exist "%sevenZipPath%" (
echo 7-Zip executable not found: "%sevenZipPath%"
exit /b 1
)
if not exist "%zipFile%" (
echo ZIP archive not found: "%zipFile%"
exit /b 1
)
if not exist "%outputDir%" (
mkdir "%outputDir%"
if errorlevel 1 (
echo Could not create destination: "%outputDir%"
exit /b 1
)
)
"%sevenZipPath%" x "%zipFile%" -o"%outputDir%"
exit /b %errorlevel%
バッチファイルからWindows ShellとVBScriptを使う
WindowsのバッチファイルからWindows Script Hostを呼び出し、Shellの自動化オブジェクトを利用できます。ShellのFolder.CopyHereメソッドについては、Microsoftの説明を参照してください。次の.bat例は、一時的なVBScriptファイルを一式書き出し、最初に展開先ディレクトリ、次に入力ZIPアーカイブを渡して、cscriptの終了後に一時ファイルを削除します。例のパスはC:\Work\sample.zipとC:\Work\sample-extractedです。実行前に自分の環境に合わせて置き換えてください。スクリプトはWindows Shellで各名前空間を開けるか確認し、利用できないパスを報告します。
@echo off
setlocal
set "zipFile=C:\Work\sample.zip"
set "outputDir=C:\Work\sample-extracted"
set "scriptFile=%TEMP%\extract-zip-%RANDOM%.vbs"
if not exist "%zipFile%" (
echo ZIP archive not found: "%zipFile%"
exit /b 1
)
if not exist "%outputDir%" (
mkdir "%outputDir%"
if errorlevel 1 (
echo Could not create destination: "%outputDir%"
exit /b 1
)
)
> "%scriptFile%" (
echo Dim shell, destination, source
echo Set shell = CreateObject^("Shell.Application"^)
echo Set destination = shell.NameSpace^(WScript.Arguments^(0^)^)
echo If destination Is Nothing Then
echo WScript.Echo "Destination folder is unavailable: " ^& WScript.Arguments^(0^)
echo WScript.Quit 2
echo End If
echo Set source = shell.NameSpace^(WScript.Arguments^(1^)^)
echo If source Is Nothing Then
echo WScript.Echo "ZIP archive namespace is unavailable: " ^& WScript.Arguments^(1^)
echo WScript.Quit 3
echo End If
echo destination.CopyHere source.Items
)
if errorlevel 1 (
echo Could not write temporary VBScript: "%scriptFile%"
exit /b 1
)
cscript //nologo "%scriptFile%" "%outputDir%" "%zipFile%"
set "scriptStatus=%errorlevel%"
del "%scriptFile%" >nul 2>&1
if not "%scriptStatus%"=="0" (
echo Windows Script Host returned status %scriptStatus%.
exit /b %scriptStatus%
)
echo CopyHere was requested; check the destination separately before using extracted files.
exit /b 0
この方法では、Windows Script HostとShellのZIP処理機能を使います。一時VBScriptでは、引数0が展開先フォルダー、引数1が入力ZIPアーカイブです。CopyHereはファイルのコピーが終わる前に戻ることがあるため、cscriptが正常終了しても、展開完了の証明にはなりません。バッチファイルのメッセージが示すのは、コピー要求から制御が戻ったことだけです。後続のコマンドで展開済みファイルを移動、削除、または読み取る場合は、アーカイブと展開先に合った完了確認を別途追加してください。このWindows固有の方法は、未実行の例として示しています。
複数のZIPファイルの展開を自動化する
入力ディレクトリにあるZIPファイルを順に処理し、アーカイブごとに別の展開先ディレクトリを用意します。展開先を分けると、異なるアーカイブに同名のファイルがあっても上書きを防げます。このバッチファイルは例示用のパスを設定し、入力ディレクトリを確認して、出力ルートを作成します。また、ディレクトリの作成や展開に失敗した場合は、その内容を報告します。いずれかのアーカイブで失敗した場合、またはZIPファイルが見つからない場合は、ステータス1で終了します。
@echo off
setlocal
set "sourceDir=C:\Work\incoming"
set "outputRoot=C:\Work\extracted"
set "found=0"
set "failed=0"
if not exist "%sourceDir%\" (
echo Source directory not found: "%sourceDir%"
exit /b 1
)
if not exist "%outputRoot%\" (
mkdir "%outputRoot%"
if errorlevel 1 (
echo Could not create output root: "%outputRoot%"
exit /b 1
)
)
for %%F in ("%sourceDir%\*.zip") do if exist "%%~fF" call :extract "%%~fF" "%%~nF"
if "%found%"=="0" (
echo No ZIP files found in: "%sourceDir%"
exit /b 1
)
if "%failed%"=="1" exit /b 1
echo All ZIP files were extracted successfully.
exit /b 0
:extract
set "found=1"
set "destination=%outputRoot%\%~2"
if not exist "%destination%\" (
mkdir "%destination%"
if errorlevel 1 (
echo Could not create destination for "%~1": "%destination%"
set "failed=1"
exit /b 0
)
)
tar -xf "%~1" -C "%destination%"
if errorlevel 1 (
echo Extraction failed for: "%~1"
set "failed=1"
) else (
echo Extracted "%~1" to "%destination%"
)
exit /b 0
ここで%%~fFは処理中のアーカイブのフルパスに、%%~nFは.zip拡張子を除いた名前に展開されます。各アーカイブは、outputRootの下に作成される、対応する名前のサブディレクトリへ展開されます。入力ディレクトリがない場合や、出力ルートを作成できない場合、スクリプトは直ちに非ゼロのステータスで終了します。アーカイブごとの展開先の作成やtarによる展開に失敗すると、対象のパスを表示してバッチ処理を失敗扱いにし、残りのアーカイブの処理を続けます。そのような失敗がひとつでもあれば、最後のステータスは非ゼロになります。該当するZIPファイルがない場合も、メッセージを表示して非ゼロで終了します。対話型のコマンドプロンプトでは%%Fではなく%Fを使います。パーセント記号を2つ重ねるのはバッチファイル内で使う場合です。このtarコマンド例はWindows向けで、ここでは実行されていません。
バッチでのZIP展開に関するトラブルシューティング
- コマンドが見つからない: 使用しているWindows環境で
tarが利用できるか確認してください。7-Zipの場合は、7-Zipがインストールされていることと、sevenZipPathが7z.exeを指していることを確認します。必要なtarがない古いWindows環境では、7-Zipなど、インストール済みの展開ツールを使ってください。 - 空白を含むパスが分割される: 例のように、アーカイブと展開先のパスを引用符で囲んでください。7-Zipでは、展開先を引用符で囲む場合も、
-oの直後にパスを続けます。たとえば-o"C:\Work Files\Extracted"のように指定します。 - 展開先を開けない、または作成できない: 親ディレクトリが存在することと、使用中のアカウントに書き込み権限があることを確認してください。展開先を先に作成し、ファイルのパスではなくフォルダーを指定します。
- ファイルが不足している、または展開が完了していないように見える: 入力パスが目的のZIPアーカイブを指していること、ファイルがZIP形式であること、アーカイブを開けることを確認してください。展開ツールの終了ステータスも確認します。ShellとVBScriptの
CopyHereを使う場合は、展開されたファイルを使う前に、非同期処理が完了するまで待つ必要があります。 - 複数のアーカイブに同名のファイルが含まれている: すべての内容をひとつの展開先に送るのではなく、ループ例のようにアーカイブごとに別のディレクトリへ展開してください。
- 別のシェルでコマンドの動作が異なる: これらのバッチ構文例はWindowsコマンドプロンプト(CMD)向けです。BashやPowerShellの構文ではないため、そのまま貼り付けて使わないでください。