I know the similar questions were asked here a lot, but I'm not completely satisfied with the answers (and even with the questions).
The main goal is compatibility - it should be applicable to widest possible range of Windows machines (including XP, Vista, and Server 2003 - which together still holds around 20% of Windows share) and produced files should be usable on Unix/Mac machines (so standard archiving/compression formats are preferable).
What the options are:
Simply select All file types, add . bat after filename, and click the Save button. Now, go to the created batch file and double-click on it to execute the zipping script. It will create an archive folder in the specified location.
And here are the answer(s):
It's possible thanks to Frank Westlake's ZIP.CMD and UNZIP.CMD(needs admin permissions and requires FSUTIL
and CERTUTIL
) .For Win2003 and WinXP it will require 2003 Admin Tool Pack which will install CERTUTIL
. Be careful as ZIP.CMD syntax is backward :
ZIP.CMD destination.zip source.file
And it can zip only single files.
I've spent some time to create a single jscript/batch hybrid script for common usage that zips/unzips files and directories (plus few more features).Here's a link to it (it became too big to post in the answer). Can be used directly with its .bat
extension and does not create any temp files. I hope the help message is descriptive enough of how it can be used.
Some examples:
// unzip content of a zip to given folder.content of the zip will be not preserved (-keep no).Destination will be not overwritten (-force no) call zipjs.bat unzip -source C:\myDir\myZip.zip -destination C:\MyDir -keep no -force no // lists content of a zip file and full paths will be printed (-flat yes) call zipjs.bat list -source C:\myZip.zip\inZipDir -flat yes // lists content of a zip file and the content will be list as a tree (-flat no) call zipjs.bat list -source C:\myZip.zip -flat no // prints uncompressed size in bytes zipjs.bat getSize -source C:\myZip.zip // zips content of folder without the folder itself call zipjs.bat zipDirItems -source C:\myDir\ -destination C:\MyZip.zip -keep yes -force no // zips file or a folder (with the folder itslelf) call zipjs.bat zipItem -source C:\myDir\myFile.txt -destination C:\MyZip.zip -keep yes -force no // unzips only part of the zip with given path inside call zipjs.bat unZipItem -source C:\myDir\myZip.zip\InzipDir\InzipFile -destination C:\OtherDir -keep no -force yes call zipjs.bat unZipItem -source C:\myDir\myZip.zip\InzipDir -destination C:\OtherDir // adds content to a zip file call zipjs.bat addToZip -source C:\some_file -destination C:\myDir\myZip.zip\InzipDir -keep no call zipjs.bat addToZip -source C:\some_file -destination C:\myDir\myZip.zip
Some known issues during zipping:
The script detects if error message pops-up and stops the execution and informs for the possible reasons.At the moment I have no way to detect the text inside the pop-up and give the exact reason for the failure.
Compressing a file is easy - makecab file.txt "file.cab"
. Eventually MaxCabinetSize could be increased. Compressing a folder requires a usage DestinationDir directive (with relative paths) for every (sub)directory and the files within . Here's a script:
;@echo off ;;;;; rem start of the batch part ;;;;; ; ;for %%a in (/h /help -h -help) do ( ; if /I "%~1" equ "%%~a" if "%~2" equ "" ( ; echo compressing directory to cab file ; echo Usage: ; echo( ; echo %~nx0 "directory" "cabfile" ; echo( ; echo to uncompress use: ; echo EXPAND cabfile -F:* . ; echo( ; echo Example: ; echo( ; echo %~nx0 "c:\directory\logs" "logs" ; exit /b 0 ; ) ; ) ; ; if "%~2" EQU "" ( ; echo invalid arguments.For help use: ; echo %~nx0 /h ; exit /b 1 ;) ; ; set "dir_to_cab=%~f1" ; ; set "path_to_dir=%~pn1" ; set "dir_name=%~n1" ; set "drive_of_dir=%~d1" ; set "cab_file=%~2" ; ; if not exist %dir_to_cab%\ ( ; echo no valid directory passed ; exit /b 1 ;) ; ;break>"%tmp%\makecab.dir.ddf" ; ;setlocal enableDelayedExpansion ;for /d /r "%dir_to_cab%" %%a in (*) do ( ; ; set "_dir=%%~pna" ; set "destdir=%dir_name%!_dir:%path_to_dir%=!" ; (echo(.Set DestinationDir=!destdir!>>"%tmp%\makecab.dir.ddf") ; for %%# in ("%%a\*") do ( ; (echo("%%~f#" /inf=no>>"%tmp%\makecab.dir.ddf") ; ) ;) ;(echo(.Set DestinationDir=!dir_name!>>"%tmp%\makecab.dir.ddf") ; for %%# in ("%~f1\*") do ( ; ; (echo("%%~f#" /inf=no>>"%tmp%\makecab.dir.ddf") ; ) ;makecab /F "%~f0" /f "%tmp%\makecab.dir.ddf" /d DiskDirectory1=%cd% /d CabinetNameTemplate=%cab_file%.cab ;rem del /q /f "%tmp%\makecab.dir.ddf" ;exit /b %errorlevel% ;; ;;;; rem end of the batch part ;;;;; ;;;; directives part ;;;;; ;; .New Cabinet .set GenerateInf=OFF .Set Cabinet=ON .Set Compress=ON .Set UniqueFiles=ON .Set MaxDiskSize=1215751680; .set RptFileName=nul .set InfFileName=nul .set MaxErrors=1 ;; ;;;; end of directives part ;;;;;
Example usage:
call cabDir.bat ./myDir compressedDir.cab
For decompression EXPAND cabfile -F:* .
can be used.For extraction in Unix cabextract or 7zip can be used.
I preferred a Jscript.net as it allows a neat hybridization with .bat (no toxic output , and no temp files).Jscript does not allow passing a reference of object to a function so the only way I found to make it work is by reading/writing files byte by byte (so I suppose it's not the fastest way - how buffered reading/writing can be done?)Again can be used only with single files.
@if (@X)==(@Y) @end /* JScript comment @echo off setlocal for /f "tokens=* delims=" %%v in ('dir /b /s /a:-d /o:-n "%SystemRoot%\Microsoft.NET\Framework\*jsc.exe"') do ( set "jsc=%%v" ) if not exist "%~n0.exe" ( "%jsc%" /nologo /out:"%~n0.exe" "%~dpsfnx0" ) %~n0.exe %* endlocal & exit /b %errorlevel% */ import System; import System.Collections.Generic; import System.IO; import System.IO.Compression; function CompressFile(source,destination){ var sourceFile=File.OpenRead(source); var destinationFile=File.Create(destination); var output = new GZipStream(destinationFile,CompressionMode.Compress); Console.WriteLine("Compressing {0} to {1}.", sourceFile.Name,destinationFile.Name, false); var byteR = sourceFile.ReadByte(); while(byteR !=- 1){ output.WriteByte(byteR); byteR = sourceFile.ReadByte(); } sourceFile.Close(); output.Flush(); output.Close(); destinationFile.Close(); } function UncompressFile(source,destination){ var sourceFile=File.OpenRead(source); var destinationFile=File.Create(destination); var input = new GZipStream(sourceFile, CompressionMode.Decompress, false); Console.WriteLine("Decompressing {0} to {1}.", sourceFile.Name, destinationFile.Name); var byteR=input.ReadByte(); while(byteR !== -1){ destinationFile.WriteByte(byteR); byteR=input.ReadByte(); } destinationFile.Close(); input.Close(); } var arguments:String[] = Environment.GetCommandLineArgs(); function printHelp(){ Console.WriteLine("Compress and uncompress gzip files:"); Console.WriteLine("Compress:"); Console.WriteLine(arguments[0]+" -c source destination"); Console.WriteLine("Uncompress:"); Console.WriteLine(arguments[0]+" -u source destination"); } if (arguments.length!=4){ Console.WriteLine("Wrong arguments"); printHelp(); Environment.Exit(1); } switch (arguments[1]){ case "-c": CompressFile(arguments[2],arguments[3]); break; case "-u": UncompressFile(arguments[2],arguments[3]); break; default: Console.WriteLine("Wrong arguments"); printHelp(); Environment.Exit(1); }
Example usage:
//zip call netzip.bat -c my.file my.zip //unzip call netzip.bat -u my.zip my.file
With the latest builds of windows 10 now we have TAR command ,though it's not the most backward compatible option:
//compress directory tar -cvf archive.tar c:\my_dir //extract to dir tar -xvf archive.tar.gz -C c:\data //compres to zip format tar -caf archive.zip c:\my_dir
amazing solutions!
The makecab solution has some issues so here is a fixed version that solves the problem when using directories with blank spaces.
;@echo off ;;;;; rem start of the batch part ;;;;; ; ;for %%a in (/h /help -h -help) do ( ; if /I "%~1" equ "%%~a" if "%~2" equ "" ( ; echo compressing directory to cab file ; echo Usage: ; echo( ; echo %~nx0 "directory" "cabfile" ; echo( ; echo to uncompress use: ; echo EXPAND cabfile -F:* . ; echo( ; echo Example: ; echo( ; echo %~nx0 "c:\directory\logs" "logs" ; exit /b 0 ; ) ; ) ; ; if "%~2" EQU "" ( ; echo invalid arguments.For help use: ; echo %~nx0 /h ; exit /b 1 ;) ; ; set "dir_to_cab=%~f1" ; ; set "path_to_dir=%~pn1" ; set "dir_name=%~n1" ; set "drive_of_dir=%~d1" ; set "cab_file=%~2" ; ; if not exist "%dir_to_cab%\" ( ; echo no valid directory passed ; exit /b 1 ;) ; ;break>"%tmp%\makecab.dir.ddf" ; ;setlocal enableDelayedExpansion ;for /d /r "%dir_to_cab%" %%a in (*) do ( ; ; set "_dir=%%~pna" ; set "destdir=%dir_name%!_dir:%path_to_dir%=!" ; (echo(.Set DestinationDir=!destdir!>>"%tmp%\makecab.dir.ddf") ; for %%# in ("%%a\*") do ( ; (echo("%%~f#" /inf=no>>"%tmp%\makecab.dir.ddf") ; ) ;) ;(echo(.Set DestinationDir=!dir_name!>>"%tmp%\makecab.dir.ddf") ; for %%# in ("%~f1\*") do ( ; ; (echo("%%~f#" /inf=no>>"%tmp%\makecab.dir.ddf") ; ) ;makecab /F "%~f0" /f "%tmp%\makecab.dir.ddf" /d DiskDirectory1="%cd%" /d CabinetNameTemplate=%cab_file%.cab ;rem del /q /f "%tmp%\makecab.dir.ddf" ;exit /b %errorlevel% ;; ;;;; rem end of the batch part ;;;;; ;;;; directives part ;;;;; ;; .New Cabinet .set GenerateInf=OFF .Set Cabinet=ON .Set Compress=ON .Set UniqueFiles=ON .Set MaxDiskSize=1215751680; .set RptFileName=nul .set InfFileName=nul .set MaxErrors=1 ;; ;;;; end of directives part ;;;;;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With