Can you zip a file from the command prompt using ONLY Windows' built-in capability to zip files?

I have a batch file that outputs a text file. I thought it would be nice if I could zip it up too.

This will be used in an uncontrolled environment, so I can't make assumptions about the presence of third-party software products such as 7-Zip, etc. This needs to use Windows' now-built-in capability to zip files.


Solution 1:

Here is an all batch file solution (a variation of my other answer) that will zip a file named c:\ue_english.txt and put it in C:\someArchive.zip:

set FILETOZIP=c:\ue_english.txt

set TEMPDIR=C:\temp738
rmdir %TEMPDIR%
mkdir %TEMPDIR%
xcopy /s %FILETOZIP% %TEMPDIR%

echo Set objArgs = WScript.Arguments > _zipIt.vbs
echo InputFolder = objArgs(0) >> _zipIt.vbs
echo ZipFile = objArgs(1) >> _zipIt.vbs
echo CreateObject("Scripting.FileSystemObject").CreateTextFile(ZipFile, True).Write "PK" ^& Chr(5) ^& Chr(6) ^& String(18, vbNullChar) >> _zipIt.vbs
echo Set objShell = CreateObject("Shell.Application") >> _zipIt.vbs
echo Set source = objShell.NameSpace(InputFolder).Items >> _zipIt.vbs
echo objShell.NameSpace(ZipFile).CopyHere(source) >> _zipIt.vbs
echo wScript.Sleep 2000 >> _zipIt.vbs

CScript  _zipIt.vbs  %TEMPDIR%  C:\someArchive.zip

pause

Write access is required to the parent of the folder stored in TEMPDIR. As this is often not the case for the root of drive C TEMPDIR may have to be changed.

Write access is also required for the folder the .bat script is in (as it generates a file there).

Also, please note that the file extension for the compressed file must be .zip. Attempts to use another extension may result in a script error. Instead, generate the .zip file and rename it.

Solution 2:

It is possible to zip files without installation of any additional software (I have tested it). The solution is:

Run this in a command-line window to create a ZIP file named C:\someArchive.zip containing all files in folder C:\test3:

CScript  zip.vbs  C:\test3  C:\someArchive.zip

Where file zip.vbs contains:

' Get command-line arguments.
Set objArgs = WScript.Arguments
Set FS = CreateObject("Scripting.FileSystemObject")
InputFolder = FS.GetAbsolutePathName(objArgs(0))
ZipFile = FS.GetAbsolutePathName(objArgs(1))

' Create an empty ZIP file.
CreateObject("Scripting.FileSystemObject").CreateTextFile(ZipFile, True).Write "PK" & Chr(5) & Chr(6) & String(18, vbNullChar)

Set objShell = CreateObject("Shell.Application")

Set source = objShell.NameSpace(InputFolder).Items

objShell.NameSpace(ZipFile).CopyHere(source)

' Required to let the ZIP command execute
' If this script randomly fails or the ZIP file is not complete,
' just increase to more than 2 seconds
wScript.Sleep 2000

I haven't tested it for paths and file names containing spaces. It may work if quotes are put around the command line parameters.


How it works: the built-in zip functionality in Windows (Windows XP and later?) is exposed through COM interfaces from the Windows shell, explorer.exe - that is the "Shell.Application" part. This COM interface can be used from a VBScript script because such a script can access COM components. To make the script fully self-contained it creates an empty ZIP file to get started (one could also create an empty ZIP file and copy it to the target system along with the VBScript script).

VBScript has been installed by default in every desktop release of Microsoft Windows since Windows 98.

CScript.exe is part of Windows Script Host. Windows Script Host is distributed and installed by default on Windows 98 and later versions of Windows. It is also installed if Internet Explorer 5 (or a later version) is installed.

Solution 3:

Windows 10 build 17063 or later is bundled with tar.exe which is capable of working with ZIP files from the command line.

tar.exe -xf archive.zip

Or to create a ZIP archive:

tar.exe -a -cf Test.zip Test

Solution 4:

If you are open to using PowerShell, zip capabilities are available in .NET 2.0 (PowerShell is .NET). Here's an a example (source) credit to Mike Hodnick:

########################################################
# out-zip.ps1
#
# Usage:
#    To zip up some files:
#       ls c:\source\*.txt | out-zip c:\target\archive.zip $_
#
#    To zip up a folder:
#       gi c:\source | out-zip c:\target\archive.zip $_
########################################################

$path = $args[0]
$files = $input

if (-not $path.EndsWith('.zip')) {$path += '.zip'} 

if (-not (test-path $path)) { 
  set-content $path ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18)) 
} 

$ZipFile = (new-object -com shell.application).NameSpace($path) 
$files | foreach {$zipfile.CopyHere($_.fullname)}

Solution 5:

You can eliminate the risk of timing out during compression by polling for existence of the compression dialog window. This method also handles the user cancelling out of the compression window.

objShell.NameSpace(ZipFile).CopyHere(source)

' Wait for compression window to open
set scriptShell = CreateObject("Wscript.Shell")
Do While scriptShell.AppActivate("Compressing...") = FALSE   
   WScript.Sleep 500 ' Arbitrary polling delay
Loop  

' Wait for compression to complete before exiting script
Do While scriptShell.AppActivate("Compressing...") = TRUE   
   WScript.Sleep 500 ' Arbitrary polling delay
Loop