Czy możesz spakować plik z wiersza poleceń, używając TYLKO wbudowanej funkcji Windows do spakowania plików?


111

Mam plik wsadowy, który wyświetla plik tekstowy. Pomyślałem, że byłoby miło, gdybym mógł go również spakować.

Będzie to używane w niekontrolowanym środowisku, więc nie mogę przyjmować założeń dotyczących obecności oprogramowania innych firm, takiego jak 7-Zip itp. Musi to wykorzystywać wbudowaną w Windows zdolność do spakowania plików.


1
czy możesz użyć skryptów Powershell lub WSH? może to być jedyny sposób na użycie wbudowanej obsługi zip w Windows z wiersza poleceń. w przeciwnym razie, jak zauważa Molly, potrzebujesz narzędzia innej firmy.
szarlatan

1
więc przesyłasz komuś plik wsadowy i nie możesz wysłać mu małego, statycznie połączonego gzip.exe?
akira

Pytanie OP jest doskonałe (pomimo dziwnego oskarżenia @ quackquixote). Ponieważ system Windows udostępnia to jako jedno kliknięcie w SendTo, w pliku BAT powinno znajdować się polecenie. To dobre pytanie, nawet jeśli odpowiedź brzmi Nie i trzeba (śmiesznie) uciekać się do korzystania z narzędzia innej firmy, które może, ale nie musi, być równoważne.
Jon Coombs

Ten link autorstwa Tomasa ma dobrze napisany skrypt do spakowania zawartości folderu. Aby to działało, po prostu skopiuj skrypt do pliku wsadowego i uruchom go, określając folder do skompresowania (źródło). Nie trzeba wspominać o katalogu docelowym, ponieważ jest on domyślnie ustawiony w skrypcie na Pulpit („% USERPROFILE% \ Desktop”)
Abhijeet

3
Najprościej byłoby w poleceniu cmd: powershell.exe Compress-Archive file-to-zip.txt zippedfile.zip(działa również z folderem)
ThomasGuenet,

Odpowiedzi:


85

Oto rozwiązanie całego pliku wsadowego (odmiana mojej innej odpowiedzi), które skompresuje plik o nazwie c:\ue_english.txti umieści go w C:\someArchive.zip:

set FILETOZIP=c:\ue_english.txt

set TEMPDIR=C:\temp738
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%  C:\someArchive.zip

pause

Dostęp do zapisu jest wymagany dla rodzica folderu przechowywanego w TEMPDIR. Ponieważ często tak nie jest w przypadku katalogu głównego dysku C TEMPDIRmoże być konieczna zmiana.

Dostęp do zapisu jest również wymagany dla folderu, w którym .batznajduje się skrypt (ponieważ generuje tam plik).

Należy również pamiętać, że rozszerzenie pliku skompresowanego musi mieć postać .zip. Próby użycia innego rozszerzenia mogą spowodować błąd skryptu. Zamiast tego wygeneruj .zipplik i zmień jego nazwę.


3
@ quack Trzymałem się w nadziei na jakieś niejasne polecenie, o którym nie wiedziałem. Widzę, jak możesz uznać to za trudne wymaganie, jeśli nie istnieje, nie oznaczało to, że nikogo nie chciałeś.
Aaron Bush,

@PeterMortensen: To może być lub nie być interesujące zobaczyć, jak bardzo jest to uproszczone dzięki PowerShell. Oto 5-liniowy przykład , ale istnieje również polecenie write-zipcmdlet, które można pobrać z Pscx .
Tamara Wijsman

Użyłem zip.exe i cywin1.dll (3mb), aby zaspokoić ZIP, a użycie to jedna linia ... od samego zipu przy użyciu jakiegoś kodu wsadowego. Wiem, że mogę użyć bancompile php z argv i przekazać do niego plik. Brzmi nieźle. „Zip z wiersza poleceń systemu Windows” to stary film science fiction, prawda?
erm3nda,

Dlaczego musimy korzystać z folderu tymczasowego TEMPDIR? Myślę, że Twoim celem jest zawinięcie pliku FILETOZIPw folder, prawda?
Nam G VU

@Peter Mortensen, wiem, że to stary wątek i to jest prawie to, czego szukam. Czy istnieje opcja kompresji jednego dużego pliku na mniejsze fragmenty?
JohnG

38

Możliwe jest skompresowanie plików bez instalowania dodatkowego oprogramowania (przetestowałem to). Rozwiązaniem jest:

Uruchom to w oknie wiersza polecenia, aby utworzyć plik ZIP o nazwie C:\someArchive.zipzawierający wszystkie pliki w folderze C:\test3:

CScript  zip.vbs  C:\test3  C:\someArchive.zip

Gdzie plik zip.vbszawiera:

' Get command-line arguments.
Set objArgs = WScript.Arguments
Set FS = CreateObject("Scripting.FileSystemObject")
InputFolder = FS.GetAbsolutePathName(objArgs(0))
ZipFile = FS.GetAbsolutePathName(objArgs(1))

' Create an empty ZIP file.
CreateObject("Scripting.FileSystemObject").CreateTextFile(ZipFile, True).Write "PK" & Chr(5) & Chr(6) & String(18, vbNullChar)

Set objShell = CreateObject("Shell.Application")

Set source = objShell.NameSpace(InputFolder).Items

objShell.NameSpace(ZipFile).CopyHere(source)

' Required to let the ZIP command execute
' If this script randomly fails or the ZIP file is not complete,
' just increase to more than 2 seconds
wScript.Sleep 2000

Nie przetestowałem go pod kątem ścieżek i nazw plików zawierających spacje. Może to zadziałać, jeśli wokół parametrów wiersza poleceń zostaną umieszczone cudzysłowy.


Jak to działa: wbudowana funkcja zip w systemie Windows (Windows XP i nowszy?) Jest udostępniana przez interfejsy COM z powłoki Windows explorer.exe - czyli części „Shell.Application”. Tego interfejsu COM można używać ze skryptu VBScript, ponieważ taki skrypt może uzyskiwać dostęp do komponentów COM. Aby skrypt był w pełni samodzielny, na początek tworzy pusty plik ZIP (można również utworzyć pusty plik ZIP i skopiować go do systemu docelowego wraz ze skryptem VBScript).

VBScript jest instalowany domyślnie w każdym wydaniu systemu Microsoft Windows na komputer od wersji Windows 98.

CScript.exejest częścią Windows Script Host . Windows Script Host jest domyślnie dystrybuowany i instalowany w systemie Windows 98 i nowszych wersjach systemu Windows. Jest także instalowany, jeśli zainstalowany jest Internet Explorer 5 (lub nowszy).


1
+1 Dobre rozwiązanie, które „uruchomi się”, ale wybieram BAT z kilku innych powodów, których nie wymieniono. Wolałbym więc rozwiązanie BAT.
Aaron Bush

4
@Aaron Bush: ten skrypt i Beaner udostępniają polecenie, które zamyka plik w linii poleceń, używając wbudowanych funkcji systemu Windows, zgodnie z żądaniem. możesz dodać to polecenie do pliku wsadowego, jak każde inne.
quack quixote

Zauważ, że przekazywane ścieżki muszą być bezwzględne, a nie względne. Musiałem także użyć technik w odpowiedzi tutaj: stackoverflow.com/q/1645843/99640
Chuck Wilbur

Ścieżki muszą być absolutne i wydaje się, że losowo zawodzi :(
kixorz

To powinno być wybrane jako odpowiedź.
The Duke Of Marshall שלום

12

Jeśli jesteś otwarty na używanie PowerShell , możliwości zip są dostępne w .NET 2.0 (PowerShell to .NET). Oto przykład ( źródło ) autorstwa Mike'a Hodnicka :

########################################################
# out-zip.ps1
#
# Usage:
#    To zip up some files:
#       ls c:\source\*.txt | out-zip c:\target\archive.zip $_
#
#    To zip up a folder:
#       gi c:\source | out-zip c:\target\archive.zip $_
########################################################

$path = $args[0]
$files = $input

if (-not $path.EndsWith('.zip')) {$path += '.zip'} 

if (-not (test-path $path)) { 
  set-content $path ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18)) 
} 

$ZipFile = (new-object -com shell.application).NameSpace($path) 
$files | foreach {$zipfile.CopyHere($_.fullname)}

Jest to w zasadzie to samo, co kod CScript w innych odpowiedziach. Żadne funkcje .NET nie są używane (a .NET i tak nie obsługuje ZIP). Podejrzewam, że może to być również wrażliwe na problem z czasem.
Robert Schmidt

2
W wersji 4.5 dodano klasę .NET System.IO.Compression.ZipFile.
Beton Głuptak

7

Możesz wyeliminować ryzyko przekroczenia limitu czasu podczas kompresji poprzez odpytywanie o istnienie okna dialogowego kompresji. Ta metoda obsługuje również anulowanie użytkownika przez okno kompresji.

objShell.NameSpace(ZipFile).CopyHere(source)

' Wait for compression window to open
set scriptShell = CreateObject("Wscript.Shell")
Do While scriptShell.AppActivate("Compressing...") = FALSE   
   WScript.Sleep 500 ' Arbitrary polling delay
Loop  

' Wait for compression to complete before exiting script
Do While scriptShell.AppActivate("Compressing...") = TRUE   
   WScript.Sleep 500 ' Arbitrary polling delay
Loop

1
+1. Te kodowe małpy .Sleep(whatever)sprawiają, że jestem chory.
ivan_pozdeev

1
Jeśli korzystam z vbs z powyższą logiką oczekiwania, jak to będzie obsługiwane, jeśli zostanie uruchomione za pomocą zaplanowanego zadania (w którym żaden użytkownik nie jest fizycznie zalogowany.)
Wes

5

Jeśli jesteś w stanie zainstalować Resource Kit Tools , znajdziesz narzędzie wiersza poleceń o nazwie COMPRESS, które może tworzyć skompresowane pliki archiwów, takie jak zip.

Microsoft (R) File Compression Utility  Version 5.00.2134.1
Copyright (C) Microsoft Corp. 1990-1999.  All rights reserved.

Compresses one or more files.

COMPRESS [-r] [-d] [-z] Source Destination
COMPRESS -r [-d] [-z] Source [Destination]

  -r            Rename compressed files.
  -d            Update compressed files only if out of date.
  -zx           LZX compression.
  -z            MS-ZIP compression.
  -zq[n]        Quantum compression and optional level
                (in range 1-7, default is 4).
  Source        Source file specification.  Wildcards may be used.
  Destination   Destination file | path specification.
                Destination may be a directory.
                If Source is multiple files and -r is not specified,
                Destination must be a directory.

3
+1 Tak naprawdę nie rozwiązuje problemów, ale nadal warto o nich wiedzieć.
Aaron Bush

3
'Keep script waiting until compression is done
Do Until objShell.NameSpace( ZipFile ).Items.Count = objShell.NameSpace( InputFolder ).Items.Count
    WScript.Sleep 200
Loop

dokładnie to, czego szukałem .. ale powoduje błąd „brak na pustym pliku zip”
Sonic Soul

Z jakiegoś powodu nigdy się to nie zwiększa, jeśli drukuję objShell.NameSpace( ZipFile ).Items.Countwewnątrz pętli, zawsze wynosi 0, nawet jeśli plik zip jest tworzony i zawiera oczekiwaną zawartość ...
Thom Nichols

2

Wiele plików / katalogów z uproszczonym kodem.

cscript zip.vbs target.zip sourceFile1 sourceDir2 ... sourceObjN

plik zip.vbs

Set objArgs = WScript.Arguments
ZipFile = objArgs(0)

' Create empty ZIP file and open for adding
CreateObject("Scripting.FileSystemObject").CreateTextFile(ZipFile, True).Write "PK" & Chr(5) & Chr(6) & String(18, vbNullChar)
Set zip = CreateObject("Shell.Application").NameSpace(ZipFile)

' Add all files/directories to the .zip file
For i = 1 To objArgs.count-1
  zip.CopyHere(objArgs(i))
  WScript.Sleep 10000 'REQUIRED!! (Depending on file/dir size)
Next

2

To jest mutacja przyjętej odpowiedzi. Wykonuję mnóstwo zadań automatyzacji nawet do tysięcy plików jednocześnie, więc nie mogę spać przez 2 sekundy i nie przejmować się tym. Zebrałem tutaj obejście , które jest podobne do odpowiedzi Jiří Kočary tutaj .

Spowoduje to pingowanie folderu docelowego co 200 ms, co jest w przybliżeniu tak szybkie, jak Microsoft mówi, aby sprawdzić dostępność aktualizacji FS.

Set parameters = WScript.Arguments
Set FS = CreateObject("Scripting.FileSystemObject")
SourceDir = FS.GetAbsolutePathName(parameters(0))
ZipFile = FS.GetAbsolutePathName(parameters(1))
CreateObject("Scripting.FileSystemObject").CreateTextFile(ZipFile, True).Write "PK" & Chr(5) & Chr(6) & String(18, vbNullChar)
Set shell = CreateObject("Shell.Application")
Set source_objects = shell.NameSpace(SourceDir).Items
Set ZipDest = shell.NameSpace(ZipFile)
Count=ZipDest.Items().Count
shell.NameSpace(ZipFile).CopyHere(source_objects)
Do While Count = ZipDest.Items().Count
    wScript.Sleep 200
Loop

1

Oto moja próba podsumowania okien wbudowanych możliwości kompresji i dekompresji - https://stackoverflow.com/questions/28043589/how-can-i-compres-zip-and-uncopress-unzip-files-and-folders -z-partią-f

z kilkoma podanymi rozwiązaniami, które powinny działać na prawie każdym komputerze z systemem Windows.

Jeśli chodzi o shell.application i WSH, wolałem jscript, ponieważ pozwala on na hybrydowy plik wsadowy / jscript (z rozszerzeniem .bat), które nie wymagają plików tymczasowych. W jednym pliku umieściłem funkcje rozpakowywania i zip oraz kilka innych funkcji .


0

Jeśli w systemie Windows 8 lub Windows Server 2012 masz PowerShell i .NET 4.5, możesz to zrobić:

zip.ps1 (użycie :)-directory <directory to zip up> -name <zip name> :

param (
    [string]$directory,
    [string]$name
)

Add-Type -Assembly System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::CreateFromDirectory($directory, $name, [System.IO.Compression.CompressionLevel]::Optimal, $false)

zip.bat (jeśli potrzebujesz pomocnika, aby wywołać program PowerShell, katalog jest pierwszym argumentem, a nazwa zip drugim):

@Echo Off
powershell -ExecutionPolicy ByPass -Command "& '%~dpn0.ps1' -directory '%1' -name '%2'"

0

Windows 10 build 17063 lub nowszy jest dołączony do tar.exe, który jest zdolny do pracy z zip z linii poleceń.

tar.exe -xf archive.zip

lub stworzyć archiwum

tar.exe -cf Test.zip Test

-5

Wiersz poleceń systemu Windows udostępnia teraz polecenie kompaktowe, które, o ile wiem, jest rodzime dla systemu Windows. To powinno spełnić wymagane wymagania, chyba że coś przeoczyłem.


9
compactistniał od XP i jest narzędziem do zarządzania kompresją NTFS
Der Hochstapler
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.