Monthly Archives: December 2007

CabIt!

I hesitated about posting this because I was talking to Steve last week about someone that had a Ruby fetish, much like someone else seems to have picked up a Python fetish.  I then realized that one could make a case that I have a Batch script fetish, seeing as how I’ve made three posts with it.  I actually really like Perl, but those skills have gotten rusty as it’s not installed natively on a Windows machine.  That’s why I turn to batch scripts sometimes–those scripts will work on all boxes.

Something else that’s not natively installed in Windows is the ability to zip a file from a command line.  (Please correct me if I’m wrong.)  I presume there are legal issues with bundling this functionality with the OS.  Instead, Windows gives the ability to create CABinets.  I couldn’t find any good (quick/dirty) documentation on how to make a single CAB from a number of files, while preserving hierarchy (ie. folders).  I was eventually forced to wade through the official SDK to figure out how to do this.

So here’s a simple script I "whipped" up through trial and error (it actually took a lot of time to figure out what options to give MakeCab.exe).  Give it a path and it will CAB up everything under that path into a file "Zipped.cab".  Admittedly, there are some ‘hacks’ here, as I think CABs were originally intended to zip up files to span across disks (like floppies).

 

REM ———–
REM * CAB IT! *
REM ———–
:CABIT

set OUTPUT=Zipped.cab

set DIRECTIVEFILE=%TEMP%Schema.ddf
set TARGET=%1
set TEMPFILE=%TEMP%TEMP

if not exist %TARGET% (
    echo %TARGET% does not exist.
    goto :EOF
)

pushd %TARGET%

echo. > %DIRECTIVEFILE%
echo .set CabinetNameTemplate=%OUTPUT%
                                 >> %DIRECTIVEFILE%
echo .set DiskDirectoryTemplate= >> %DIRECTIVEFILE%
echo .set InfFileName=%TEMPFILE% >> %DIRECTIVEFILE%
echo .set RptFileName=%TEMPFILE% >> %DIRECTIVEFILE%
echo .set MaxDiskSize=0          >> %DIRECTIVEFILE%
echo .set CompressionType=LZX    >> %DIRECTIVEFILE%

call :CAB_DIR .

MakeCab /f %DIRECTIVEFILE%

del /f %DIRECTIVEFILE%
del /f %TEMPFILE%

popd

goto :EOF

REM CAB Helper
:CAB_DIR
echo .set DestinationDir=%1 >> %DIRECTIVEFILE%
for /f %%i in (‘dir /b /a:-d %1’) do (
    echo %1%%i >> %DIRECTIVEFILE%
)
for /f %%i in (‘dir /b /a:d %1’) do (
    call :CAB_DIR %1%%i
)
goto :EOF

 

To extract the cab file, you would use "Extract.exe", also found natively on Windows.  Note that if you view the Cab in Windows Explorer, you don’t actually see hierarchy like you do with zipped files.  That threw me off for a bit; weird behaviour.  Using "Extract.exe" would deflate the file into its hierarchy, or you can use Explorer to unzip specific files.

Notes:

  • I couldn’t figure out how to get MakeCab to stop generating the .inf and .rpt files either, so my workaround for that is kind of ugly.
  • MakeCab doesn’t like empty directories, so it’ll spit out errors.  But I think you can safely ignore them.

Comments welcome.