batch script to zip a folder without using external softwares

后端 未结 2 907
广开言路
广开言路 2020-12-06 22:44

I have folder with the following structure

folder subfolder(empty) subfolder file1.bat file2.bat file3.bat

How do I go about writing a batch f

相关标签:
2条回答
  • 2020-12-06 23:39

    With Shell.Application level 1 empty folders are always skipped.You can test by yourself with selecting a bunch of files including empty folders and try to paste them in a zip file through windows explorer (which is actually what is used by shell application).As workaround you can copy the folder you want in another empty folder and zip the new folder. Then you'll have level 2 empty directories which should be zipped.

    0 讨论(0)
  • 2020-12-06 23:41

    As npocmaka said, Windows can't add a single empty folder to a zip file either through scripting or drag-and-dropping.

    But you've inspired me. I decided to write a zip utility in JScript, just to see whether I could. To address your current problem, I added a check for empty folders. If an empty folder is encountered, this script will create a new child folder within called "(empty)". It was either that, add a 0-byte file, or throw an error and skip adding the folder.

    Anyway, if you'd like to try it, save this script with a .bat extension and run it. Granted, it's not as simple as your VBscript, but it's got better logging, error handling, and timing; and it can zip individual files as well as folders.

    @if (@a==@b) @end   /* JScript ignores this multiline comment
    
    :: zip.bat file/folder1 [file/folder2 [file/folder3 etc...]] [-o outfile.zip]
    :: creates a zip file
    
    @echo off
    setlocal enabledelayedexpansion
    
    if "%~1"=="" (
        echo Usage: %~nx0 [-o outfile.zip] "file1 or folder1" ["file2 or folder2"] etc.
        echo If -o is not used, the zip file is named based on the first infile.
        goto :EOF
    )
    
    :: convert wildcards to individual filenames
    for %%I in (%*) do (
        echo(%%I | findstr "[\*\?]" >NUL && (
            for /f "tokens=*" %%x in ('dir /b %%I') do set "args=!args! "%%~fx""
        ) || set "args=!args! "%%~I""
    )
    
    if "!args!" equ "" (
        echo(%* does not exist.
        goto :EOF
    )
    cscript /nologo /e:Jscript "%~f0" !args!
    
    goto :EOF
    
    :: end of batch portion / begin JScript portion */
    var files = [], outfile,
        fso = new ActiveXObject("scripting.filesystemobject"),
        shl = new ActiveXObject("shell.application");
    
    function chr(n) { return String.fromCharCode(n); }
    
    for (var i=0; i<WSH.Arguments.length; i++) {
        if (WSH.Arguments(i).toLowerCase() == '-o') outfile = WSH.Arguments(++i);
        else files.push(WSH.Arguments(i));
    }
    if (!outfile) try { outfile = files[0].split(/[\/\\]/)[0] + '.zip'; }
    catch(e) { outfile = 'archive.zip'; } // Probably never see this, but just in case.
    
    WSH.Echo('Creating ' + outfile);
    
    var zip = fso.CreateTextFile(outfile);
    zip.Write("PK" + chr(5) + chr(6));
    for (var i=18; i>0; i--) zip.Write(chr(0));
    zip.Close()
    zip = shl.NameSpace(fso.GetFile(outfile).Path);
    
    for (var i=0; i<files.length; i++) {
        try {
            if (fso.FileExists(files[i])) {
                var file = fso.GetFile(files[i]);
            } else if (fso.FolderExists(files[i])) {
                var file = fso.GetFolder(files[i]);
                if (!shl.NameSpace(file.Path).Items().Count) {
                    // Windows can't add an empty folder to a zip file, but
                    // it *can* add a folder that contains an empty folder.
                    shl.NameSpace(file.Path).NewFolder('(empty)');
                }
            } else {
                throw "Unable to locate " + files[i];
            }
            var folder = shl.NameSpace(file.ParentFolder + '\\'),
            zipThis = folder.ParseName(fso.GetFileName(files[i]));
        }
        catch(e) {
            var output = 'Skipping ' + files[i] + ': ';
            output += (typeof e === 'string') ? e : (
                e.description ? e.description : 'error ' + e.number + ' (unspecified error)'
            );
            WSH.Echo(output);
            files.splice(i--,1);
            continue;
        }
        WSH.StdOut.Write('Compressing ' + fso.GetFileName(file) + '... ');
        zip.CopyHere(zipThis);
        while (zip.Items().Count <= i) {
            WSH.Sleep(50);
        }
        WSH.Echo('Done.  (' + zip.Items().Count + ' of ' + files.length + ')');
    }
    
    if (!zip.Items().Count) {
        fso.DeleteFile(fso.GetFile(outfile));
        WSH.Echo('Zip file is empty.  Deleting.');
    }
    

    The advantage of using JScript over VBScript here is that there's no need to echo out to _zipIt.vbs. JScript affords the ability to be evaluated inline as a hybrid of a batch script. Your vbscript you plundered has another issue, in that it arbitrarily calls WScript.Sleep 2000, regardless of how much time is needed to complete the copy. If you're copying large files, 2 seconds might not be enough time. And it's wasteful if you're copying something small.

    0 讨论(0)
提交回复
热议问题