Brett Klamer

Backup Script in Batch

This is used to exchange files between two non-networked computers (using a USB flash drive). It's written for a single file to be transferred between the same directories on both computers. The main benefit is just the automatic checksum matching. A warning for others: I'm a complete novice to batch scripting and this really should have been all PowerShell code.

Backup

@echo off
cls

echo ----------------------
echo  Backup Program Files
echo ----------------------

rem Find the USB drive and save its drive lettter.
for /f "usebackq tokens=1,2,3,4 " %%i in (`wmic logicaldisk get caption^,description^,drivetype 2^>NUL`) do (
	if %%l equ 2 (
		set usb_dir=%%i\
	)
)

if %usb_dir% == [] (
	echo I couldn't find a USB drive.
	goto end
)

echo USB drive connected at %usb_dir%

choice /m "Is this the correct USB drive?"

if errorlevel 2 goto no
if errorlevel 1 goto yes

goto end

:no
echo You selected No. Insert one USB drive or backup manually.
goto end

:yes
rem Create zero padded time stamp. YYYY-MM-DD_HH-mm
set hour=%time:~0,2%
if "%hour:~0,1%" == " " (
	set hour=0%hour:~1,1%
)
set datetime=%date:~10,4%-%date:~4,2%-%date:~7,2%_%hour%-%time:~3,2%

rem Use powershell (>=4) to calculate an MD5 checksum.
echo Creating a checksum ...
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "D:\directory\utils\checksum-backup.ps1 %usb_dir% %datetime%"

echo Copying backup ...
copy D:\directory\file.vhd %usb_dir%file-%datetime%.vhd

echo Backup located on the USB drive at %usb_dir%file-%datetime%.vhd
echo You may exit this dialog and remove the USB drive.
goto end

:end
pause
# checksum-backup.ps1
# Requires Powershell >= v4
$usb_dir=$args[0]
$datetime=$args[1]
$path = Join-Path -Path $usb_dir -ChildPath "file-$datetime.vhd.md5"
dir D:\directory\file.vhd | Get-FileHash -Algorithm MD5 | Format-List -Property Hash | Out-File -Encoding utf8 $path

Restore

@echo off
cls

echo -----------------------
echo  Restore Program Files
echo -----------------------

rem Find the USB drive and save its drive lettter.
for /f "usebackq tokens=1,2,3,4 " %%i in (`wmic logicaldisk get caption^,description^,drivetype 2^>NUL`) do (
	if %%l equ 2 (
		set usb_dir=%%i\
	)
)

if %usb_dir% == [] (
	echo I couldn't find a USB drive.
	goto end
)

rem The flags are important for ordering. See `dir /?` for more info.
for /f "delims=|" %%I in ('DIR "%usb_dir%file*.vhd" /b /o:nd') do (
	set newest_file=%%I
)

echo Are you sure you want to restore %usb_dir%%newest_file% ?

choice /m "Press Y for Yes or N for No."

if errorlevel 2 goto no
if errorlevel 1 goto yes

goto end

:no
echo You selected No
goto end

:yes
echo You selected Yes (Quickly exit the dialog if this was a mistake.)
timeout /t 10
echo Copying new file ...
copy %usb_dir%%newest_file% D:\directory\file.vhd.tmp
echo Creating checksum ...
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "D:\directory\utils\checksum-restore.ps1"
echo Comparing checksums ...
fc D:\directory\file.vhd.tmp.md5 %usb_dir%%newest_file%.md5 > NUL
if errorlevel 1 goto error
echo Checksums match ...
echo Saving old file ...
copy D:\directory\file.vhd D:\directory\file.vhd.previous
echo Restoring new file ...
move /y D:\directory\file.vhd.tmp D:\directory\file.vhd
del D:\directory\file.vhd.tmp.md5
echo Program has been updated. Enjoy!
goto end

:error
echo ------------------------------------
echo  Checksum mismatch! Restore failed!
echo ------------------------------------
echo Removing bad file from D:\ ...
del D:\directory\file.vhd.tmp
del D:\directory\file.vhd.tmp.md5
echo Try again with a new backup or restore manually.
goto end

:end
pause
# checksum-restore.ps1
# Requires Powershell >= v4
dir D:\directory\file.vhd.tmp | Get-FileHash -Algorithm MD5 | Format-List -Property Hash | Out-File -Encoding utf8 D:\directory\file.vhd.tmp.md5