如何使用批处理文件压缩(/ zip)和解压(/ unzip)文件和文件夹,而不使用任何外部工具?

时间:2022-08-16 23:58:41

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

我知道这里有很多类似的问题,但我对答案(甚至是问题)并不完全满意。

The main goal is compatibility - it should be applicable to widest possible range of windows machines (including XP,Vista,Win2003 - 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).

它的主要目标是兼容性——它应该适用于最广泛的windows机器(包括XP、Vista、Win2003——它们仍然拥有大约20%的windows份额),并且产生的文件应该在Unix/Mac机器上可用(所以标准的归档/压缩格式更可取)。

What the options are :

选择是什么:

  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 WinXP Home Edition)
  2. 创建实现某种zip算法的批处理。显然,这是可能的——但是只使用单个文件,并使用CERTUTIL进行二进制处理(一些机器默认没有CERTUTIL,并且不可能安装在WinXP Home Edition上)
  3. Using shell.application through WSH.The best option according to me.It allows zipping whole directories and is usable on every windows machine
  4. 使用shell。应用程序通过WSH。我认为是最好的选择。它允许对整个目录进行压缩,并且适用于所有windows机器
  5. Makecab - despite its compression is not so portable its available on every windows machine.Some external programs like 7zip 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.
  6. Makecab -尽管它的压缩在每个windows机器上都不是很便携。一些像7zip这样的外部程序可以提取. cab内容,但是当需要在Unix/Mac上使用文件时就不那么方便了。虽然压缩单个文件非常简单,但是保存目录结构需要更多的努力。
  7. Using .NET Framework - not so good option.Form .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 Win2003 , but as it is highly probable to have .NET 2.0 up-to 4.0 it's a considerable opion.
  8. 使用。net框架-不是很好的选择。形式。net 2.0 GZipStream但它允许压缩只有单一文件。net 4.5 Zip功能但不支持Vista和XP,更多- net XP和Win2003不是默认安装,但它是非常可能的。net 2.0达到4.0,这是一个相当大的见解。
  9. Powershell - as it relies on .NET it has same capabilities.It's not installed by default on XP,2003 and Vista so I'll skip it.
  10. Powershell——因为它依赖于。net,所以它也有同样的功能。它不是默认安装在XP,2003和Vista上,所以我跳过它。

3 个解决方案

#1


52  

And here are the answer(s):

答案是:

1.Using "pure" batch script to zip/unzip file.

1。使用“纯”批处理脚本压缩/解压缩文件。

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 :

多亏了弗兰克·韦斯特莱克的拉链。CMD并解压缩。CMD(需要管理权限,需要FSUTIL和CERTUTIL)。对于Win2003和WinXP,它需要2003年的管理工具包来安装CERTUTIL。小心ZIP。CMD语法是向后的:

ZIP.CMD destination.zip source.file

And it can zip only single files.

而且它只能压缩单个文件。

2.Using Shell.Application

2。使用Shell.Application

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.

我已经花了一些时间来创建一个jscript/batch混合脚本,用于压缩/解压缩文件和目录(再加上一些其他特性)的通用使用。这里有一个链接(它太大了以至于不能在答案中发布)。可以直接使用它的.bat扩展名,不创建任何临时文件。我希望帮助消息足够描述如何使用它。

Some examples:

一些例子:

// 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

Some known issues during zipping:

一些已知的问题在zipping:

  • 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.
  • 如果系统驱动器上没有足够的空间(通常是C:),脚本可能会产生各种错误,通常脚本会停止。这是壳层造成的。应用程序积极使用%TEMP%文件夹来压缩/解压缩数据。
  • Folders and files that contain unicode symbols in their names cannot be handled by Shell.Application object.
  • 在名称中包含unicode符号的文件夹和文件不能由Shell处理。应用程序对象。
  • Max supported size of produced zip files is around 8gb in Vista and above and around 2gb in XP/2003
  • 在Vista和以上版本中,最大支持的zip文件大小在8gb左右,在XP/2003版本中大约为2gb

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.

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

3.Makecab.

3. makecab。

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:

压缩文件很容易- makecab文件。txt文件。出租车”。最终可以增加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 ;;;;;

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

对于解压缩,展开cabfile -F:*。可以使用。可以使用Unix cabextract或7zip中的提取。

4. .NET and GZipStream

4 . net和GZipStream

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.

我更喜欢Jscript.net,因为它允许使用.bat(没有有毒输出,也没有临时文件)进行整齐的杂交。Jscript不允许将对象的引用传递给函数,所以我发现让它工作的唯一方法是逐字节地读取/写入文件(因此我认为这不是最快的方法——如何进行缓冲的读取/写入?)同样,只能使用单个文件。

@if (@X)==(@Y) @end /* JScript comment
@echo off
setlocal

for /f "tokens=* delims=" %%v in ('dir /b /s /a:-d  /o:-n "%SystemRoot%\Microsoft.NET\Framework\*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);
}

#2


4  

amazing solutions!

神奇的解决方案!

The makecab solution has some issues so here is a fixed version that solves the problem when using directories with blank spaces.

makecab解决方案有一些问题,所以这里有一个固定的版本,可以在使用空格的目录时解决这个问题。

;@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 ;;;;;

#3


1  

CAB.bat [input] folder or file : pack | .cab or .??_ : unpack | none : pack a files subfolder
Will also add a CAB entry to right-click SendTo menu for easy handling
Since this one does both tasks seamlessly, it should be preferred over the ugly makecab one - why use hybrid script if you write to temp file anyway?

出租车。bat[输入]文件夹或文件:打包| .cab or .?_:解压|没有:打包文件文件夹也将添加一个出租车进入右键发送到菜单简单无缝地处理这一任务以来,它应该优先于丑makecab——为什么使用混合脚本如果写入临时文件呢?

@echo off &echo. &set "ext=%~x1" &title CAB [%1] &rem input file or folder / 'files' folder / unpacks .cab .??_
if "_%1"=="_" if not exist "%~dp0files" echo CAB: No input and no 'files' directory to pack &goto :Exit "do nothing"
if "_%1"=="_" if exist "%~dp0files" call :CabDir "%~dp0files" &goto :Exit "input = none, use 'files' directory -pack" 
for /f "tokens=1 delims=r-" %%I in ("%~a1") do if "_%%I"=="_d" call :CabDir "%~f1" &goto :Exit "input = dir -pack"
if not "_%~x1"=="_.cab" if not "_%ext:~-1%"=="__" call :CabFile "%~f1" &goto :Exit "input = file -pack"
call :CabExtract "%~f1" &goto :Exit "input = .cab or .??_ -unpack" 
:Exit AveYo: script will add a CAB entry to right-click -- SendTo menu
if not exist "%APPDATA%\Microsoft\Windows\SendTo\CAB.bat" copy /y "%~f0" "%APPDATA%\Microsoft\Windows\SendTo\CAB.bat" >nul 2>nul
ping -n 6 localhost >nul &title cmd.exe &exit /b
:CabExtract %1:[.cab or .xx_]
echo %1 &pushd "%~dp1" &mkdir "%~n1" >nul 2>nul &expand -R "%~1" -F:* "%~n1" &popd &goto :eof
:CabFile %1:[filename]
echo %1 &pushd "%~dp1" &makecab /D CompressionType=LZX /D CompressionLevel=7 /D CompressionMemory=21 "%~nx1" "%~n1.cab" &goto :eof   
:CabDir %1:[directory]
dir /a:-D/b/s "%~1"
set "ddf="%temp%\ddf""
echo/.New Cabinet>%ddf%
echo/.set Cabinet=ON>>%ddf%
echo/.set CabinetFileCountThreshold=0;>>%ddf%
echo/.set Compress=ON>>%ddf%
echo/.set CompressionType=LZX>>%ddf%
echo/.set CompressionLevel=7;>>%ddf%
echo/.set CompressionMemory=21;>>%ddf%
echo/.set FolderFileCountThreshold=0;>>%ddf%
echo/.set FolderSizeThreshold=0;>>%ddf%
echo/.set GenerateInf=OFF>>%ddf%
echo/.set InfFileName=nul>>%ddf%
echo/.set MaxCabinetSize=0;>>%ddf%
echo/.set MaxDiskFileCount=0;>>%ddf%
echo/.set MaxDiskSize=0;>>%ddf%
echo/.set MaxErrors=1;>>%ddf%
echo/.set RptFileName=nul>>%ddf%
echo/.set UniqueFiles=ON>>%ddf%
setlocal enabledelayedexpansion
pushd "%~dp1"
for /f "tokens=* delims=" %%D in ('dir /a:-D/b/s "%~1"') do (
 set "DestinationDir=%%~dpD" &set "DestinationDir=!DestinationDir:%~1=!" &set "DestinationDir=!DestinationDir:~0,-1!"
 echo/.Set DestinationDir=!DestinationDir!;>>%ddf%
 echo/"%%~fD"  /inf=no;>>%ddf%
)
makecab /F %ddf% /D DiskDirectory1="" /D CabinetNameTemplate=%~nx1.cab &endlocal &popd &del /q /f %ddf% &goto :eof

#1


52  

And here are the answer(s):

答案是:

1.Using "pure" batch script to zip/unzip file.

1。使用“纯”批处理脚本压缩/解压缩文件。

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 :

多亏了弗兰克·韦斯特莱克的拉链。CMD并解压缩。CMD(需要管理权限,需要FSUTIL和CERTUTIL)。对于Win2003和WinXP,它需要2003年的管理工具包来安装CERTUTIL。小心ZIP。CMD语法是向后的:

ZIP.CMD destination.zip source.file

And it can zip only single files.

而且它只能压缩单个文件。

2.Using Shell.Application

2。使用Shell.Application

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.

我已经花了一些时间来创建一个jscript/batch混合脚本,用于压缩/解压缩文件和目录(再加上一些其他特性)的通用使用。这里有一个链接(它太大了以至于不能在答案中发布)。可以直接使用它的.bat扩展名,不创建任何临时文件。我希望帮助消息足够描述如何使用它。

Some examples:

一些例子:

// 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

Some known issues during zipping:

一些已知的问题在zipping:

  • 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.
  • 如果系统驱动器上没有足够的空间(通常是C:),脚本可能会产生各种错误,通常脚本会停止。这是壳层造成的。应用程序积极使用%TEMP%文件夹来压缩/解压缩数据。
  • Folders and files that contain unicode symbols in their names cannot be handled by Shell.Application object.
  • 在名称中包含unicode符号的文件夹和文件不能由Shell处理。应用程序对象。
  • Max supported size of produced zip files is around 8gb in Vista and above and around 2gb in XP/2003
  • 在Vista和以上版本中,最大支持的zip文件大小在8gb左右,在XP/2003版本中大约为2gb

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.

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

3.Makecab.

3. makecab。

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:

压缩文件很容易- makecab文件。txt文件。出租车”。最终可以增加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 ;;;;;

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

对于解压缩,展开cabfile -F:*。可以使用。可以使用Unix cabextract或7zip中的提取。

4. .NET and GZipStream

4 . net和GZipStream

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.

我更喜欢Jscript.net,因为它允许使用.bat(没有有毒输出,也没有临时文件)进行整齐的杂交。Jscript不允许将对象的引用传递给函数,所以我发现让它工作的唯一方法是逐字节地读取/写入文件(因此我认为这不是最快的方法——如何进行缓冲的读取/写入?)同样,只能使用单个文件。

@if (@X)==(@Y) @end /* JScript comment
@echo off
setlocal

for /f "tokens=* delims=" %%v in ('dir /b /s /a:-d  /o:-n "%SystemRoot%\Microsoft.NET\Framework\*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);
}

#2


4  

amazing solutions!

神奇的解决方案!

The makecab solution has some issues so here is a fixed version that solves the problem when using directories with blank spaces.

makecab解决方案有一些问题,所以这里有一个固定的版本,可以在使用空格的目录时解决这个问题。

;@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 ;;;;;

#3


1  

CAB.bat [input] folder or file : pack | .cab or .??_ : unpack | none : pack a files subfolder
Will also add a CAB entry to right-click SendTo menu for easy handling
Since this one does both tasks seamlessly, it should be preferred over the ugly makecab one - why use hybrid script if you write to temp file anyway?

出租车。bat[输入]文件夹或文件:打包| .cab or .?_:解压|没有:打包文件文件夹也将添加一个出租车进入右键发送到菜单简单无缝地处理这一任务以来,它应该优先于丑makecab——为什么使用混合脚本如果写入临时文件呢?

@echo off &echo. &set "ext=%~x1" &title CAB [%1] &rem input file or folder / 'files' folder / unpacks .cab .??_
if "_%1"=="_" if not exist "%~dp0files" echo CAB: No input and no 'files' directory to pack &goto :Exit "do nothing"
if "_%1"=="_" if exist "%~dp0files" call :CabDir "%~dp0files" &goto :Exit "input = none, use 'files' directory -pack" 
for /f "tokens=1 delims=r-" %%I in ("%~a1") do if "_%%I"=="_d" call :CabDir "%~f1" &goto :Exit "input = dir -pack"
if not "_%~x1"=="_.cab" if not "_%ext:~-1%"=="__" call :CabFile "%~f1" &goto :Exit "input = file -pack"
call :CabExtract "%~f1" &goto :Exit "input = .cab or .??_ -unpack" 
:Exit AveYo: script will add a CAB entry to right-click -- SendTo menu
if not exist "%APPDATA%\Microsoft\Windows\SendTo\CAB.bat" copy /y "%~f0" "%APPDATA%\Microsoft\Windows\SendTo\CAB.bat" >nul 2>nul
ping -n 6 localhost >nul &title cmd.exe &exit /b
:CabExtract %1:[.cab or .xx_]
echo %1 &pushd "%~dp1" &mkdir "%~n1" >nul 2>nul &expand -R "%~1" -F:* "%~n1" &popd &goto :eof
:CabFile %1:[filename]
echo %1 &pushd "%~dp1" &makecab /D CompressionType=LZX /D CompressionLevel=7 /D CompressionMemory=21 "%~nx1" "%~n1.cab" &goto :eof   
:CabDir %1:[directory]
dir /a:-D/b/s "%~1"
set "ddf="%temp%\ddf""
echo/.New Cabinet>%ddf%
echo/.set Cabinet=ON>>%ddf%
echo/.set CabinetFileCountThreshold=0;>>%ddf%
echo/.set Compress=ON>>%ddf%
echo/.set CompressionType=LZX>>%ddf%
echo/.set CompressionLevel=7;>>%ddf%
echo/.set CompressionMemory=21;>>%ddf%
echo/.set FolderFileCountThreshold=0;>>%ddf%
echo/.set FolderSizeThreshold=0;>>%ddf%
echo/.set GenerateInf=OFF>>%ddf%
echo/.set InfFileName=nul>>%ddf%
echo/.set MaxCabinetSize=0;>>%ddf%
echo/.set MaxDiskFileCount=0;>>%ddf%
echo/.set MaxDiskSize=0;>>%ddf%
echo/.set MaxErrors=1;>>%ddf%
echo/.set RptFileName=nul>>%ddf%
echo/.set UniqueFiles=ON>>%ddf%
setlocal enabledelayedexpansion
pushd "%~dp1"
for /f "tokens=* delims=" %%D in ('dir /a:-D/b/s "%~1"') do (
 set "DestinationDir=%%~dpD" &set "DestinationDir=!DestinationDir:%~1=!" &set "DestinationDir=!DestinationDir:~0,-1!"
 echo/.Set DestinationDir=!DestinationDir!;>>%ddf%
 echo/"%%~fD"  /inf=no;>>%ddf%
)
makecab /F %ddf% /D DiskDirectory1="" /D CabinetNameTemplate=%~nx1.cab &endlocal &popd &del /q /f %ddf% &goto :eof