批处理脚本在不使用外部软件的情况下压缩文件夹

时间:2014-12-03 13:46:47

标签: batch-file zip

我有以下结构的文件夹

夹    子文件夹(空)    子文件夹    file1.bat    file2.bat    file3.bat

如何在不使用winrar或7zip等外部软件的情况下编写批处理文件来压缩上述文件夹的内容?

我尝试了以下代码。但是它会将内容复制到指定的临时文件夹而不包含空文件夹,并且在尝试压缩文件夹时,它只会压缩file1和file2并忽略其余内容。

我希望能够在不影响结构的情况下压缩文件夹。

我找不到问题的原因。任何帮助表示赞赏。

set FILETOZIP=D:\OutputZipFiles\TestWorkDemo


set TEMPDIR=D:\OutputZipFiles\TempDir
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%  D:\OutputZipFiles\someArchive.zip

pause

2 个答案:

答案 0 :(得分:5)

作为npocmaka said,Windows无法通过脚本编写或拖放操作将单个空文件夹添加到zip文件中。

但是你激励了我。我决定在JScript中编写一个zip实用程序,只是为了看看我是否可以。为了解决您当前的问题,我添加了一个空文件夹检查。如果遇到空文件夹,此脚本将在名为“(空)”内创建一个新的子文件夹。就是这样,添加一个0字节的文件,或者抛出错误并跳过添加文件夹。

无论如何,如果您想尝试一下,请使用.bat扩展名保存此脚本并运行它。当然,它并不像VBscript那么简单,但它有更好的日志记录,错误处理和时序;它可以压缩单个文件和文件夹。

@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.');
}

这里使用JScript优于VBScript的优点是不需要回显_zipIt.vbs。 JScript提供了内联评估作为批处理脚本的混合的能力。你掠夺的vbscript有另一个问题,因为它随意调用WScript.Sleep 2000,无论完成复制需要多少时间。如果您要复制大文件,2秒可能不够。如果你要复制一些小东西,那就太浪费了。

答案 1 :(得分:2)

使用Shell.Application级别1总是跳过空文件夹。您可以自行测试选择包含空文件夹的一堆文件,并尝试通过Windows资源管理器将其粘贴到zip文件中(实际上是使用的通过shell应用程序)。作为解决方法,您可以在另一个空文件夹中复制所需的文件夹并压缩新文件夹。然后你将有2级空目录,应该压缩。