Windowsの標準の機能でzip化しようとすると右クリックしかありません
zip化するdosコマンドは無いため、batでzip化することはできません
コマンドラインでzip化するためには7zip等、コマンドラインのインタフェースを準備してくれているソフトをインストールする必要があります
しかしっ!!
ソフトをインストールできない場合もあるでしょう!!
この記事ではソフトをインストールせずにzip化するbatを紹介します!
- コマンド(bat/vbs)でzip化したい
- ソフトをインストールせず、Windows標準の機能だけで実現したい
- batでサーバーからローカルへコピーしてzip化もしたい
◆解決できるかも知れないお悩み
- ソフトをインストールしなくても、bat(vbs)でzip化したい
ぜひこちらもご覧ください
Contents
Windowsにはzip化するコマンドは無いの?
無いです!
右クリックでzip化機能を提供してるのに、、、
と思って探しまくったけど、やっぱり無いんですよ
で、ググりまくると、、、、
VBスクリプトでできるよ
という情報があった!!!!
『VBスクリプトでzip化する』という視点でググりまくりました!!
zip化を実現してくれるVBスクリプトを教えてくださっている記事は何本かありました(ありがとうございます!)
何本か試してみたところ、確かにzip化してくれて僕が思ってるようなことはできるんだけど・・・・
理由は分からないんだけど、zip化してくれないファイルがあったんだよね
今回zip化したい目的はディレクトリ全体をバックアップしたいので、zip化してくれないファイルがあるのはちょいまずいなぁと・・・・
で、色々試した結果、この記事で紹介するVBスクリプトに辿り着きました
もしかしたら他にもzip化してくれないファイルがあるかも知れないけど、ひとまずはこれで。
紹介するbatとvbsの簡単な説明
やりたいこと
- サーバーにあるディレクトリ(0個以上)をローカルへバックアップ目的でコピーする
- コピーしたディレクトリはzip化して、zipのファイル名に日付と時刻を付与する
- この処理はタスクスケジューラに登録して定期的に動かす
プログラム構成
- BkupMain.bat
- サーバーのディレクトリをネットワークドライブとして接続する
- ネットワークドライブからローカルへコピーをする
- MakeZip.vbsを呼び出す
- MakeZip.vbs
- 圧縮処理をする
- 圧縮処理が終了したかどうかを3秒毎に判断する
- 圧縮処理が終了していないなら処理続行
- 圧縮処理が終了したのならプログラム終了
batプログラムとvbsプログラム
では、プログラムを以下に貼り付けておきます
GitHubにも置いてます
dir_copy_and_zip | GitHub
bat(BkupMain.bat)
@echo off REM ************************************************** REM サーバーからローカルへコピーしてzipにするbat REM REM カスタマイズするなら「★」マークの部分を変更するべし REM ************************************************** cd /d %~dp0 REM 遅延環境変数の有効化 setlocal ENABLEDELAYEDEXPANSION REM ************************************************** REM REM 変数及び定数 REM REM ************************************************** REM ================================================== REM 本日日付と時刻 REM ================================================== set TODAY_STR=%date:~2,2%%date:~5,2%%date:~8,2% set time_temp=%time: =0% set TIME_STR=%time_temp:~0,2%%time_temp:~3,2%%time_temp:~6,2% REM ================================================== REM ★擬似的な配列 REM %SERVER_UNC%の中にあるフォルダ名を書く REM REM アンダーバーの後ろの数字は配列の添字と思ってください REM batに配列は無いので、擬似的に配列っぽいものを実現している REM REM 擬似的なFOREACHで処理しているので、気にせず増減してOK REM 但し要素番号は連続したものにしてね REM ================================================== set FOLDER[0]=folder0 set FOLDER[1]=folder1 set FOLDER[2]=folder2 REM 事前チェック call set it=%%FOLDER[0]%% if not defined it ( echo バックアップ対象が設定されていないため終了します exit /b 0 ) REM ================================================== REM ★ワーキングディレクトリ REM ・サーバーからコピーするフォルダを置くところ REM ・zipファイルを置くところ REM REM サンプル→ C:\fuga\hoge\ REM ================================================== rem ★work_folderの最後には\マークを付けない set work_folder=work_fol rem ★WORKING_DIRの最後には\マークを付ける set WORKING_DIR=%~dp0%work_folder%\%TODAY_STR%\ echo %WORKING_DIR% if not exist %WORKING_DIR% ( echo ワーキングディレクトリは存在しないので作成します mkdir %WORKING_DIR% ) else ( REM どこに接続されているかわからないので一旦切断する echo ワーキングディレクトリは存在する ) REM ================================================== REM ネットワークドライブ関係の変数 REM Xドライブ REM ================================================== REM ★ドライブレター set NETWORKDRIVE=x: REM ★サーバー set SERVER_UNC=\\servername\hoge\fuga set NET_USE_CMD=net use %NETWORKDRIVE% set NETWORKDRIVE_CREATE=%NET_USE_CMD% %SERVER_UNC% set NETWORKDRIVE_DELETE=%NET_USE_CMD% /delete /y REM ================================================== REM ★VBSプログラム(zipにしてくれるやつ) REM ================================================== set VBS_FILE=cscript MakeZip.vbs REM ================================================== REM ★タイムアウト REM ================================================== set TIMEOUT_SEC=5 REM ************************************************** REM REM 本処理 REM REM ************************************************** REM ================================================== REM ネットワークドライブが存在していたら切断する REM ================================================== if not exist %NETWORKDRIVE% ( echo ネットワークドライブは存在しない ) else ( REM どこに接続されているか分からないので一旦切断する echo ネットワークドライブは存在するので一旦強制的に切断します %NETWORKDRIVE_DELETE% ) REM ================================================== REM ネットワークドライブ接続 REM ================================================== echo ネットワークドライブを接続します %NETWORKDRIVE_CREATE% REM ================================================== REM バックアップ処理をする REM ================================================== REM FOLDER配列っぽいものででFOREACHっぽい処理をする REM ※batにはFOREACHの命令は無いので擬似的なもの REM -------------------------------------------------- REM サーバーからローカルへコピー REM -------------------------------------------------- set i=0 :FOREACH_COPY call set it=%%FOLDER[!i!]%% if defined it ( echo %NETWORKDRIVE%\!it! REM サーバーからローカルへコピー set XCOPY_CMD=xcopy /s /e /i /h /k /q %NETWORKDRIVE%\!it! %WORKING_DIR%!it! echo %XCOPY_CMD% call %XCOPY_CMD% REM 次の要素へ移動 set /A i+=1 goto :FOREACH_COPY ) REM -------------------------------------------------- REM コピーの終了を検知することができないので、数秒待つことにする REM ※コピー元/先のサイズを比較すれば終了が分かる思うが、 REM 面倒なので数秒待つだけにする REM -------------------------------------------------- timeout /t %TIMEOUT_SEC% /nobreak REM -------------------------------------------------- REM ZIP化 REM -------------------------------------------------- set i=0 :FOREACH_ZIP call set it=%%FOLDER[!i!]%% if defined it ( echo !it! REM vbsでzipにする set PARAM1=%WORKING_DIR%!it! set PARAM2=!PARAM1!_%TODAY_STR%_%TIME_STR%.zip set ZIP_CMD=%VBS_FILE% !PARAM1! !PARAM2! echo %ZIP_CMD% call %ZIP_CMD% REM 次の要素へ移動 set /A i+=1 goto :FOREACH_ZIP ) REM ================================================== REM ネットワークドライブ切断 REM ================================================== %NETWORKDRIVE_DELETE% REM ================================================== REM 後始末処理 REM ================================================== REM -------------------------------------------------- REM ローカルにコピーしたフォルダを削除する REM -------------------------------------------------- set i=0 :FOREACH_RMDIR call set it=%%FOLDER[!i!]%% if defined it ( echo !it! REM ローカルにコピーしたフォルダを削除する set PARAM1=%WORKING_DIR%!it! set RMDIR_CMD=rmdir /s /q !PARAM1! echo %RMDIR_CMD% call %RMDIR_CMD% REM 次の要素へ移動 set /A i+=1 goto :FOREACH_RMDIR ) REM ================================================== REM 終了 REM ================================================== exit /b 0
vbs(MakeZip.vbs)
'************************************************** ' ディレクトリをzipファイルにする ' ' ◆期待する引数 ' 1個目:対象ディレクトリ(フルパスで) ' サンプル→ C:\hoge\fuga ' 2個目:zipファイル名(フルパスで) ' サンプル→ C:\hoge\fuga.zip ' ◆注意 ' 引数のディレクトリ存在チェックはやってないよ ' ' ◆実行方法 ' > cscript MakeZip.vbs param1 param2 ' ' ◆!!重要!! ' システムファイル等を圧縮してくれないファイルがあるかも知れない ' 使用に際してはよく確認すること ' ' カスタマイズするなら「★」マークの部分を変更するべし '************************************************** Option Explicit '************************************************** ' ' ★定数 ' '************************************************** Dim COMP_END_WAIT_MSEC COMP_END_WAIT_MSEC = 3000 '************************************************** ' ' 変数 ' '************************************************** Dim str Dim Shell Dim Fso Dim WshShell Dim objFolder Dim Handle Dim EmptyData Dim strTargetZipFile Dim objTargetFolder Dim SINK Dim objWMIService Dim sv_counter Dim counter Dim ZipFile '-------------------------------------------------- ' cscriptで実行しているかの確認 '-------------------------------------------------- str = WScript.FullName str = Right(str, 11) str = Ucase(str) if str <> "CSCRIPT.EXE" then Wscript.Echo "cscript.exeで実行してください" Wscript.Quit end if '-------------------------------------------------- ' 引数があるかどうかを確認 '-------------------------------------------------- if WScript.Arguments.Count <> 2 then WScript.echo("error : Argument counts are invalid.") WScript.Quit(-1) end if ' 引数を取得 objFolder = WScript.Arguments(0) ZipFile = WScript.Arguments(1) '************************************************** ' ' 本処理 ' '************************************************** '-------------------------------------------------- ' 必要な基本オブジェクト '-------------------------------------------------- Set Shell = WScript.CreateObject("Shell.Application") Set Fso = WScript.CreateObject("Scripting.FileSystemObject") Set WshShell = WScript.CreateObject("WScript.Shell") '-------------------------------------------------- ' 空のzip書庫作成 '-------------------------------------------------- Set Handle = Fso.CreateTextFile(ZipFile, True) EmptyData = Chr(&H50) & Chr(&H4B) & Chr(&H5) & Chr(&H6) EmptyData = EmptyData & String(18, Chr(0)) Handle.Write EmptyData Handle.Close '-------------------------------------------------- ' 圧縮 '-------------------------------------------------- Set objTargetFolder = Shell.NameSpace(ZipFile) '-------------------------------------------------- ' 非同期の圧縮処理 '-------------------------------------------------- Call objTargetFolder.CopyHere(objFolder, 0) '-------------------------------------------------- ' WMI非同期イベントの監視 '-------------------------------------------------- Set SINK = WScript.CreateObject("WbemScripting.SWbemSink", "SINK_") Set objWMIService = GetObject("winmgmts:\\.\root\cimv2") objWMIService.ExecNotificationQueryAsync SINK, _ "SELECT " & _ " * " & _ "FROM " & _ " __InstanceOperationEvent WITHIN 1 " & _ "WHERE " & _ " TargetInstance ISA 'Win32_Process' " & _ " AND TargetInstance.Name = 'explorer.exe' " Wscript.Echo "ZIP保存処理を開始します(=> 終了するまで何も触らないでください)" '-------------------------------------------------- ' 圧縮処理が終了したか3秒毎に判断する '-------------------------------------------------- Do sv_counter = counter WScript.Sleep COMP_END_WAIT_MSEC if sv_counter = counter then Wscript.Echo "処理を終了します" Wscript.Quit end if Loop '================================================== ' explorer.exeの動作中に呼び出される '================================================== Sub SINK_OnObjectReady(objLatestEvent, objAsyncContext) counter = counter + 1 Wscript.Echo "... 処理中:" & objLatestEvent.TargetInstance.Name End Sub
応用したい方に…
batとvbs、2本のプログラムを管理するのって面倒だったりします
batの中でvbsファイルを生成して、使ったら削除して、みたいなことをすると、batの1本だけを管理すればオッケーみたいなこともできます
↓以前僕が作ったプログラムでは、batの中でTeraTermマクロを生成するということをやっています
batとTeraTermマクロの組み合わせ | GitHub
別にこのやり方が良いってワケじゃなく、こういうやり方もありますよというだけの話です
さいごに、
- ソフトをインストールするな
- インターネットにつなげるな
- SubversionとかRedmine等ツールを使うな
- Excelファイルで全て管理せよ!!!
と、まぁ、人力や手作業を大好きな会社の是非は置いときますが、
個人的には属人要素(人力、手作業、記憶力、チェックシート、気を付ける)に頼ってはいけないと考えています
間違えない or 間違いに気付くような仕組みが大切、ラクすればするほど質は上がると思っています
しかしソフトを入れるなみたいな制約が多い場合には、OSが持つ機能だけでなんとかする必要があります
今回のバックアップ用batとzip化用vbsはそんな制約の中で調べて作りました
Pythonとかインストールできればもっとラクに作れたとは思うんですけど、まぁ、苦肉の策です
参考書籍
プログラミング のレッスンに興味がある方、レッスン内容を聞いてみたい方、なんなりとお問い合わせください。
無料体験レッスンもありますのでお気軽にどうぞ!!!