如何在不使用任何外部工具的情况下使用批处理文件压缩 (/zip ) 和解压缩 (/unzip ) 文件和文件夹? [英] How can I compress (/ zip ) and uncompress (/ unzip ) files and folders with batch file without using any external tools?

查看:28
本文介绍了如何在不使用任何外部工具的情况下使用批处理文件压缩 (/zip ) 和解压缩 (/unzip ) 文件和文件夹?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这里经常有人问类似的问题,但我对答案(甚至是问题)并不完全满意.

I know the similar questions were asked here a lot, but I'm not completely satisfied with the answers (and even with the questions).

主要目标是兼容性 - 它应该适用于尽可能广泛的 Windows 机器(包括 XPVistaServer 2003 - 仍然拥有大约 20% 的 Windows 份额)和生成的文件应该可以在 Unix/Mac 机器上使用(因此标准归档/压缩格式是最好).

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).

选项是什么:

  1. 创建一个实现某些 zip 算法的批处理.显然这是可能的 - 但仅适用于单个文件并使用 CERTUTIL 进行二进制处理(某些机器默认没有 CERTUTIL,无法安装在 Windows XP Home Edition 上)
  2. 使用 shell.application 通过 WSH.在我看来,这是最好的选择.它允许压缩整个目录并可在每台 Windows 机器上使用
  3. Makecab - 尽管它的压缩不是那么便携,但它在每台 Windows 机器上都可用.一些外部程序如 7-Zip 能够提取 .CAB 内容,但是当需要在 Unix/Mac 上使用文件时,它会不太方便.虽然压缩单个文件非常简单,但保留目录结构需要更多的努力.
  4. 使用 .NET Framework - 不是很好的选择.从 .NET 2.0 开始,有 GZipStream,但它只允许压缩单个文件..NET 4.5 具有 Zip 功能,但在 Vista 和 XP 上不受支持.更重要的是 - XP 和 Server 2003 上默认不安装 .NET,但由于很有可能将 .NET 2.0 安装到 4.0,因此这是一个不错的选择.
  5. PowerShell - 因为它依赖于 .NET,所以它具有相同的功能.XP、Server 2003 和 Vista 上默认未安装它,因此我将跳过它.
  1. Creating a batch that implements some zip algorithm. Apparently this is possible - but only with single files and using CERTUTIL for binary processing (some machines does not have CERTUTIL by default and is not possible to be installed on Windows XP Home Edition)
  2. Using shell.application through WSH. It is the best option according to me. It allows zipping whole directories and is usable on every Windows machine
  3. Makecab - despite its compression is not so portable its available on every windows machine. Some external programs like 7-Zip are capable to extract .CAB content, but it will be not so convenient when files need to be used on Unix/Mac. And while compressing a single file is pretty straightforward, preserving directory structure requires a little bit more effort.
  4. Using .NET Framework - not so good option. From .NET 2.0 there is GZipStream, but it allows compression only of single files. .NET 4.5 has Zip capabilities, but it's not supported on Vista and XP. And even more - .NET is not installed by default on XP and Server 2003, but as it is highly probable to have .NET 2.0 up-to 4.0 it's a considerable option.
  5. PowerShell - as it relies on .NET it has same capabilities. It's not installed by default on XP, Server 2003 and Vista, so I'll skip it.

推荐答案

以下是答案:

这要归功于 Frank Westlake 的 ZIP.CMDUNZIP.CMD(需要管理员权限并需要 FSUTILCERTUTIL).对于 Win2003 和 WinXP,它将需要 2003 Admin Tool Pack 将安装 CERTUTIL.小心 ZIP.CMD 语法向后:

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

它只能压缩单个文件.

我花了一些时间来创建一个单一的 jscript/batch 混合脚本,用于压缩/解压缩文件和目录(以及更多功能)的常见用途.这是它的链接(它变得太大了在答案中发布).可以直接使用它的 .bat 扩展名,并且不创建任何临时文件.我希望帮助信息对如何使用它有足够的描述.

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.

一些例子:

// 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:myDirmyZip.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.zipinZipDir -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:myDirmyFile.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:myDirmyZip.zipInzipDirInzipFile -destination C:OtherDir -keep no -force yes
call zipjs.bat unZipItem -source C:myDirmyZip.zipInzipDir -destination C:OtherDir 

// adds content to a zip file
call zipjs.bat addToZip -source C:some_file -destination C:myDirmyZip.zipInzipDir -keep no
call zipjs.bat addToZip -source  C:some_file -destination C:myDirmyZip.zip

压缩过程中的一些已知问题:

Some known issues during zipping:

  • 如果系统驱动器(通常是 C:)上没有足够的空间,脚本可能会产生各种错误,大多数情况下脚本会停止.这是由于 Shell.Application 主动使用 %TEMP% 文件夹以压缩/解压缩数据.
  • 名称中包含 unicode 符号的文件夹和文件无法由 Shell.Application 对象处理.
  • 生成的 zip 文件的最大支持大小在 Vista 及更高版本中约为 8gb,在 XP/2003 中约为 2gb
  • if there's not enough space on the system drive (usually C:) the script could produce various errors , most often the script halts.This is due to Shell.Application actively uses %TEMP% folder to compress/decompress the data.
  • Folders and files that contain unicode symbols in their names cannot be handled by Shell.Application object.
  • Max supported size of produced zip files is around 8gb in Vista and above and around 2gb in XP/2003

脚本检测是否弹出错误消息并停止执行并通知可能的原因.目前我无法检测弹出窗口中的文本并给出失败的确切原因.

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.

压缩文件很容易 - makecab file.txt "file.cab" .最终 MaxCabinetSize 可以增加.压缩文件夹需要使用 DestinationDir 指令(带有相对路径)用于每个(子)目录和 .这是一个脚本:

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:directorylogs" "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 ;;;;;

示例用法:

call cabDir.bat ./myDir compressedDir.cab

用于解压 EXPAND cabfile -F:* . 可以使用.用于在 Unix 中提取 cabextract7zip 都可以使用.

For decompression EXPAND cabfile -F:* . can be used.For extraction in Unix cabextract or 7zip can be used.

我更喜欢 Jscript.net,因为它允许与 .bat 进行巧妙的混合(没有有毒输出,也没有临时文件).Jscript 不允许将对象的引用传递给函数,所以我发现这是实现它的唯一方法工作是逐字节读取/写入文件(所以我认为这不是最快的方法 - 如何完成缓冲读取/写入?)再次只能用于单个文件.

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.NETFramework*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);
}

示例用法:

//zip
call netzip.bat -c my.file my.zip
//unzip
call netzip.bat -u my.zip my.file

5.TAR(仅适用于最新的 Windows 版本)

使用最新版本的 Windows 10 现在我们有 TAR 命令,虽然它不是最向后兼容的选项:

5. TAR (only for the newest windows builds)

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

这篇关于如何在不使用任何外部工具的情况下使用批处理文件压缩 (/zip ) 和解压缩 (/unzip ) 文件和文件夹?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆