batch-file - create - zip files from command line
secuencia de comandos por lotes para comprimir una carpeta sin usar software externo (2)
Con Shell.Application
carpetas vacías de nivel de aplicación 1 siempre se omiten. Puede probarlas usted mismo seleccionando un grupo de archivos, incluidas las carpetas vacías, e intente pegarlas en un archivo comprimido a través de Windows Explorer (que en realidad es lo que usa la aplicación de shell). Como solución, puede copiar la carpeta que desee en otra carpeta vacía y comprimir la nueva carpeta. Luego, tendrá directorios vacíos de nivel 2 que deberían estar comprimidos.
Tengo una carpeta con la siguiente estructura
subcarpeta de la carpeta (vacía) subcarpeta file1.bat file2.bat file3.bat
¿Cómo hago para escribir un archivo por lotes para comprimir el contenido de la carpeta anterior sin usar softwares externos como winrar o 7zip?
Probé el siguiente código. Pero copiaría los contenidos en la carpeta temporal especificada sin la carpeta vacía y al intentar comprimir la carpeta solo se comprimiría el archivo1 y el archivo2 e ignoraría el resto de los contenidos.
Me gustaría poder comprimir la carpeta tal como está sin afectar la estructura.
No pude encontrar el motivo del problema. Cualquier ayuda es apreciada.
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
Como dijo npocmaka , Windows no puede agregar una sola carpeta vacía a un archivo zip, ya sea a través de scripts o arrastrando y soltando.
Pero me has inspirado. Decidí escribir una utilidad de compresión en JScript, solo para ver si podía. Para resolver su problema actual, agregué un cheque para las carpetas vacías. Si se encuentra una carpeta vacía, esta secuencia de comandos creará una nueva carpeta secundaria dentro llamada "(vacía)". Fue eso, agregar un archivo de 0 bytes, o lanzar un error y omitir la adición de la carpeta.
De todos modos, si desea probarlo, guarde este script con la extensión .bat y ejecútelo. Por supuesto, no es tan simple como su VBscript, pero tiene un mejor registro, manejo de errores y tiempos; y puede comprimir archivos individuales y carpetas.
@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.'');
}
La ventaja de usar JScript sobre VBScript aquí es que no hay necesidad de repetir el eco en _zipIt.vbs
. JScript ofrece la posibilidad de ser evaluado en línea como un híbrido de un script por lotes. Su vbscript que saqueó tiene otro problema, ya que llama arbitrariamente a WScript.Sleep 2000
, independientemente de cuánto tiempo se necesita para completar la copia. Si está copiando archivos de gran tamaño, es posible que 2 segundos no sean suficientes. Y es un desperdicio si estás copiando algo pequeño.