以下是答案:
1. 使用“纯”批处理脚本压缩/解压文件。
这要归功于Frank Westlake的 ZIP.CMD 和 UNZIP.CMD(需要管理员权限并需要 FSUTIL
和 CERTUTIL
)。对于Win2003和WinXP,需要安装2003 Admin Tool Pack,它将安装 CERTUTIL
。请注意,ZIP.CMD的语法是反向的:
ZIP.CMD destination.zip source.file
同时它只能压缩单个文件。
2. 使用Shell.Application
我花了一些时间创建了一个单一的 jscript/batch 混合脚本,用于常见的文件和目录的压缩/解压 (以及其他一些功能)。这里是链接(它变得太大而不能在答案中发布)。
可以直接使用其带有.bat
扩展名的文件,并且不会创建任何临时文件。
我希望帮助信息足够描述它如何使用。
以下是一些示例:
// 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:\myDir\myZip.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.zip\inZipDir -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:\myDir\myFile.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:\myDir\myZip.zip\InzipDir\InzipFile -destination C:\OtherDir -keep no -force yes
call zipjs.bat unZipItem -source C:\myDir\myZip.zip\InzipDir -destination C:\OtherDir
// adds content to a zip file
call zipjs.bat addToZip -source C:\some_file -destination C:\myDir\myZip.zip\InzipDir -keep no
call zipjs.bat addToZip -source C:\some_file -destination C:\myDir\myZip.zip
在压缩过程中可能会出现一些已知问题:
- 如果系统驱动器(通常为 C:)上没有足够的空间,脚本可能会产生各种错误,最常见的是脚本停止。这是因为 Shell.Application 活跃地使用%TEMP% 文件夹来压缩/解压缩数据。
- 包含 Unicode 符号名称的文件夹和文件无法被 Shell.Application 对象处理。
- Vista 及以上版本支持的生成的 zip 文件最大大小约为 8GB,XP/2003 版本支持的最大大小约为 2GB。
脚本将检测是否出现错误消息并停止执行,并告知可能的原因。目前我无法检测弹出窗口内的文本并给出失败的确切原因。
压缩单个文件很容易 - makecab file.txt "file.cab"
。最终可以增加MaxCabinetSize。
压缩文件夹需要为每个(子)目录和其中的文件使用DestinationDir指令(使用相对路径)。
以下是一个脚本:
;@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:\directory\logs" "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系统中,可以使用cabextract或7zip进行提取。
.NET和GZipStream
我更喜欢使用Jscript.net,因为它可以与.bat文件无缝结合(没有有毒的输出和临时文件)。Jscript不允许将对象引用传递给函数,所以我发现唯一的使其工作的方法是逐字节读取/写入文件(因此我认为这不是最快的方法 - 该如何进行缓冲读取/写入?)同样只能用于单个文件。
@if (@X)==(@Y) @end
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命令,尽管它不是最兼容的选项:
//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
Shell.Application
方法是否有 2GB 大小限制?另外请注意,ZIP64 格式仅在 Vista 或更高版本 的Shell.Application
中得到支持。 - David RuhmannShell.Application
解决方案,压缩包中包含我的XP模式虚拟硬盘目录,总共约6.2GB。它被压缩到2.44GB。然后我使用IZArc进行解压缩,所有内容都能够无误地提取出来,并且大小与原始文件相同。这是在Win7 x64上完成的。 - rojoCompress-Archive
和Expand-Archive
。 - lit