Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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.

share|improve this question
1  
can you utilize Powershell or WSH scripting? that might be the only way to use Windows' builtin zip handling from the commandline. otherwise, as Molly points out, you need a 3rd-party tool. –  quack quixote Feb 19 '10 at 19:59
1  
so you send someone a batch file and you can not send him some tiny statically linked gzip.exe? –  akira Feb 19 '10 at 22:16

8 Answers 8

up vote 60 down vote accepted

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.

share|improve this answer
26  
ouch. that's... just painful to see. +1 for heroic effort to satisfy an increasingly ridiculous set of requirements. –  quack quixote Feb 22 '10 at 23:27
1  
@quack I was holding out in the hope of some obscure command that I didn't know about. I can see how you might find that a difficult requirement if one doesn't exist, didn't mean to put anybody out. –  Aaron Bush Mar 2 '10 at 13:56
1  
@Peter Mortensen Wow... I think I have to accept that don't I? –  Aaron Bush Mar 2 '10 at 13:57
1  
@PeterMortensen, any ideas on how to extend this so that it will include recursive folders instead of just the files within the folder specified? –  methodMan Feb 1 '13 at 23:29
2  
This is something that can only be inspired by divine revelation. –  hobs Aug 22 '13 at 15:55

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
InputFolder = objArgs(0)
ZipFile = objArgs(1)

'Create 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!
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.

share|improve this answer
    
+1 Good solution that will "Just Run", but I choose BAT for several other reasons not listed. So I would prefer a BAT solution. –  Aaron Bush Feb 22 '10 at 13:30
3  
@Aaron Bush: this script and Beaner's both provide a command that zips a file on the commandline, using windows builtin functions, as requested. you can add that command to a batchfile like any other. –  quack quixote Feb 22 '10 at 23:24
    
Note that the paths passed in have to be absolute, not relative. I had to also use the techniques in the answer here: stackoverflow.com/q/1645843/99640 –  Chuck Wilbur Jun 27 '12 at 21:08
    
Paths have to be absolute and it seems to randomly fail :( –  Napalm Feb 13 at 20:33
    
This should be selected as the answer. –  The Duke Of Marshall שלם Mar 14 at 17:48

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)}
share|improve this answer
    
This is basically the same thing as the CScript code in other answers. No .NET features are used (and .NET doesn't have ZIP support anyway). I suspect this might also be sensitive to the timing issue. –  Robert Schmidt Feb 25 at 8:14

If you are able to install the Resource Kit Tools, you will find a command line tool called COMPRESS that can create compressed archive files like zip.

Microsoft (R) File Compression Utility  Version 5.00.2134.1
Copyright (C) Microsoft Corp. 1990-1999.  All rights reserved.

Compresses one or more files.

COMPRESS [-r] [-d] [-z] Source Destination
COMPRESS -r [-d] [-z] Source [Destination]

  -r            Rename compressed files.
  -d            Update compressed files only if out of date.
  -zx           LZX compression.
  -z            MS-ZIP compression.
  -zq[n]        Quantum compression and optional level
                (in range 1-7, default is 4).
  Source        Source file specification.  Wildcards may be used.
  Destination   Destination file | path specification.
                Destination may be a directory.
                If Source is multiple files and -r is not specified,
                Destination must be a directory.
share|improve this answer
1  
+1 Doesn't really solve things, but still good to know about. –  Aaron Bush Feb 22 '10 at 13:28

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
share|improve this answer
    
+1. Those code monkey-style ".Sleep(whatever)" make me sick. –  ivan_pozdeev Jun 25 '13 at 14:30
1  
If I am running a vbs with the above logic for waiting, how will this be handled if being launched via a scheduled task (where no user is physically logged in.) –  Wescrock Jun 27 '13 at 22:05
'Keep script waiting until compression is done
Do Until objShell.NameSpace( ZipFile ).Items.Count = objShell.NameSpace( InputFolder ).Items.Count
    WScript.Sleep 200
Loop
share|improve this answer
    
exactly what i was looking for.. but it does give me an error "missing on empty Zip file" –  Sonic Soul Apr 3 at 21:25

Multiple files / directories with simplified code.

cscript zip.vbs target.zip sourceFile1 sourceDir2 ... sourceObjN

zip.vbs file

Set objArgs = WScript.Arguments
ZipFile = objArgs(0)

' Create empty ZIP file and open for adding
CreateObject("Scripting.FileSystemObject").CreateTextFile(ZipFile, True).Write "PK" & Chr(5) & Chr(6) & String(18, vbNullChar)
Set zip = CreateObject("Shell.Application").NameSpace(ZipFile)

' Add all files/directories to the .zip file
For i = 1 To objArgs.count-1
  zip.CopyHere(objArgs(i))
  WScript.Sleep 10000 'REQUIRED!! (Depending on file/dir size)
Next
share|improve this answer

The Windows command line now provides the compact command which, as far as I can tell, is native to Windows. That should meet the requirements requested unless I missed something.

share|improve this answer
6  
compact existed since XP and is a tool to manage NTFS compression –  Oliver Salzburg May 31 '13 at 20:06

protected by Community Jun 1 '13 at 16:37

Thank you for your interest in this question. Because it has attracted low-quality answers, posting an answer now requires 10 reputation on this site.

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.