ZIP Dateien automatisch unzipen und verschieben?
Hallo, folgendes Problem liegt vor. Ein System packt immer ZIP-Dateien in C:\ZIP Test, hier sollen sie automatisch entzipt werden und in C:\Downloads verschoben werden (die entzipten Ordner). Das ganze soll auf einem Server geschehen, aber ich möchte es auf meinem eigenen Rechner erstmal austesten. Ist dieses Problem mittels einer kleinen Batch lösbar und hat jemand Lösungsansätze? Danke
8 Antworten
Ich weiß nicht, ob das eigene Windows interne Zip auch ein CMD-Tool mitliefert, 7zip kann das aber auf jeden Fall.
Also lade 7zip runter muss nicht zwingend installiert sein, der Ordner reicht. Darin gibt's mehrere Programme, die "7zipFM.exe" ist das Programm mit Benutzeroberfläche, das willst Du nicht. Du brauchst die "7z.exe", die ist für die CMD gemacht.
Einfach mal in der CMD aufrufen, dann zeigt es dir mögliche Befehle an, oder Du suchst online nach der Doku dazu.
Und dann brauchst Du auch nichts verschieben, Du gibst einfach direkt den Pfad an, wo alles landen soll.
PS:
Das automatisch erkennen von neuen Dateien ist aber nicht so ohne Weiteres möglich, zumindest nicht mit Batch. C# hat den FileSystemWatcher, andere Sprachen haben andere Möglichkeiten.
Oder Du lässt dein Entpack-Skript regelmäßig von der Windows-Aufgabenverwaltung ausführen.
Ich hatte eben etwas Zeit und habe das ganze mal als klassische Batch mit JS-Hilfsscript realisiert.
Wie bereits im ersten Ansatz erwähnt ist das Ganze in punkto Resourcen ungünstig, da jedesmal das komplette Verzeichnis gescannt wird, statt auf ein Systemereignis zu warten.
@echo off
chcp 65001 >nul
set "SourceFolder=C:\zip"
set "DestinationFolder=C:\unzip"
set "ZipFileFolder=C:\downloads"
set "Delay=60" &rem wartezeit in Sekunden (5 sekunden würden das System strapazieren!)
if not exist "%temp%\unzip2.js" echo args=WScript.Arguments;if (args.length^<1){WScript.Quit()};FSO=new ActiveXObject("Scripting.FileSystemObject");ShlApp = new ActiveXObject( "Shell.Application" );ZipFile=FSO.GetAbsolutePathName(args(0));if ((FSO.GetExtensionName(ZipFile))=='') {ZipFile=FSO.GetAbsolutePathName(ZipFile+'.zip')};if (!FSO.FileExists(ZipFile)){WScript.Quit()};OutFolder='.';if (args.length^>1){OutFolder=args(1)};OutFolder= FSO.GetAbsolutePathName(OutFolder);ShlApp.NameSpace(OutFolder).CopyHere(ShlApp.NameSpace(ZipFile).Items(),20) >"%temp%\unzip2.js"
md "%ZipFileFolder%" 2>nul
rem Endlosloop
for /l %%i in (0) do (
rem finde Zipfiles
for /f "tokens=*" %%a in ('dir /b "%SourceFolder%\*.zip"') do (
echo Datei "%%a" gefunden
cscript //nologo "%temp%\unzip2.js" "%%~dpna" "%DestinationFolder%"
move /y "%%a" "%ZipFileFolder%" >nul
)
timeout %Delay% >nul
)
das Hilfsscript wirkt nur Monströs, da ich es als Einzeiler generiere.
hübsch zeilenweise sähe es so aus:
unzip2.js
args=WScript.Arguments;
if (args.length<1){
WScript.Echo ('Aufruf:\r\n'+WScript.ScriptName+' ZipFile[.zip] [OutputFolder]')
WScript.Quit()
}
FSO=new ActiveXObject("Scripting.FileSystemObject")
ShlApp = new ActiveXObject( "Shell.Application" )
ZipFile=FSO.GetAbsolutePathName(args(0))
if ((FSO.GetExtensionName(ZipFile))=='') {ZipFile=FSO.GetAbsolutePathName(ZipFile+'.zip')}
if (!FSO.FileExists(ZipFile)){WScript.Echo (ZipFile+' nicht gefunden');WScript.Quit()}
OutFolder='.'
if (args.length>1){OutFolder=args(1)}
OutFolder= FSO.GetAbsolutePathName(OutFolder)
ShlApp.NameSpace(OutFolder).CopyHere(ShlApp.NameSpace(ZipFile).Items(),20)
Kompressionstools wie WinRAR oder 7zip bieten Parameter für die Kommandozeile, die das automatische Packen und Entpacken unterstützen.
Beispiel:
C:\Programm Files (x86)\WinRAR>WinRAR x "C:\tmp\xxx.zip" "C:\tmp"
Verschieben kannst du Dateien, indem du sie kopierst (copy) und anschließend die Quelldaten löschst (del).
Geht auch automatisiert mit einem Filesystemwatcher
...und für (ent)Packen hat Powershell eine eigene Methode https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.archive/expand-archive?view=powershell-7.1
Geht auch mit C# https://docs.microsoft.com/de-de/dotnet/standard/io/how-to-compress-and-extract-files
oder klassisch per VBScript https://stackoverflow.com/a/9934879 also auch in Batch nutzbar.
...alles ohne fremde Software zu installieren.
Mit Batch eher nicht...
ist zwar mit jeder Menge Rödelei und resurcenfressendem Pollig machbar, aber nicht empfehlenswert. (...und schon garnicht mit 4 Zeilen)
...wenn es nicht C# sein soll lässt sich auch in Powershell mit den Filesystemwatcher arbeiten.
die Folgende Demo hat Netto ca. 20 Zeilen (ohne Kommentare etc.) und entpackt jedes neu im ordner c:\zip neu erzeugte zip nach Desktop.
zip_watch.ps1
$SourceFolder='C:\zip'
#Achtung! aufgerufene Variablen und Funktionen innerhalb der Callbackfunktion (Scriptblock!) Global definieren
$global:DestinationFolder='C:\unziped'
function global:ExpandZip ($ZipFile,$DestinationPath) {
#Expand-Archive
Write-Host "mache was" $ZipFile $DestinationPath
Expand-Archive $ZipFile $DestinationPath -force
}
### erzeuge einen Dateisystembeobachter
$watcher=New-Object System.IO.FileSystemWatcher
#zu beobachtender Ordner
$watcher.Path=$SourceFolder
#Dateimaske, welche Dateien beobchtet werden sollen (hier Zip)
$watcher.Filter='*.zip'
#auch Unterverzeichnisse beobachten?
$watcher.IncludeSubdirectories=$false
$watcher.EnableRaisingEvents=$false
### was soll getan werden (scriptblock variable)
$action={
# Rückgabe Datei, welche das Ereignis ausgelöst hat...
$path = $Event.SourceEventArgs.FullPath
#welche Veränderung der Auslöser war
$changeType = $Event.SourceEventArgs.ChangeType
#etwas anzeigen
Write-Host "$path was $changetype at $(get-date)"
ExpandZip $Event.SourceEventArgs.FullPath $global:DestinationFolder
}
### registriere Ereignisse, auf welche wie reagiert werden soll
#du kannst natürlich für jedes Ereignis auch eine eigene Actionvariable definieren
#...oder einfach nur das Ereignis registrieren, auf welches Du reagieren möchtest
Register-ObjectEvent $watcher "Created" -Action $action|Out-Null
#Reaktion auf andere Ereignisse für diese Demo deaktiviert
#Register-ObjectEvent $watcher "Changed" -Action $action|Out-Null
#Register-ObjectEvent $watcher "Deleted" -Action $action|Out-Null
#Register-ObjectEvent $watcher "Renamed" -Action $action|Out-Null
#Endlosschleife. Welche das Script geöffnet hält, Reaktionszeit auf Eereignisse hier 5 sekunden(kann auch länger oder Kürzer)
while ($true) {
Write-Host '.' -n;
sleep 5
}
Was das laufen im Hintergrund betrifft , sollte es kein Problem sein das Fenster zu minimieren. Das ist ein administratives Script und soll automatiesiern und keinen Schönheitspreis gewinnen🙄. Schließlich muss man als Administrator auch eingreifen können...
Natürlich könnte man das Powerschellscript auch noch in einer Hybridbatch unterbringen .
Wie das geht habe ich schon zig mal zelebriert:
zb. https://www.gutefrage.net/frage/powershell-skript-automatisch-ausfuehren#answer-394285184
oder in der Rubrik batch-trick
ps hier noch mit "wegschieben der Zip-datei:
$SourceFolder='C:\zip\' #ordner der überwacht werden soll
$global:DestinationFolder='C:\unzip' #wohin entpackt werden soll
$global:ZipFileFolder='C:\downloads\' #wohin das entpackte zip verschoben werden soll
function global:ExpandZip ($ZipFile,$DestinationPath) {
Expand-Archive $ZipFile $DestinationPath -force #zipdatei entpacken
Move-Item $ZipFile -Destination $global:ZipFileFolder -force #zipdatei verschieben
}
New-Item $global:ZipFileFolder -ItemType "directory" -force >$null #Erzeuge, wenn noch nicht existent
$watcher=New-Object System.IO.FileSystemWatcher
$watcher.Path=$SourceFolder
$watcher.Filter='*.zip'
$watcher.IncludeSubdirectories=$false
$watcher.EnableRaisingEvents=$false
$action={
$path = $Event.SourceEventArgs.FullPath
$changeType = $Event.SourceEventArgs.ChangeType
Write-Host "$path was $changetype at $(get-date)"
ExpandZip $Event.SourceEventArgs.FullPath $global:DestinationFolder
}
Register-ObjectEvent $watcher "Created" -Action $action|Out-Null
while ($true) {sleep 5}
Sollte kein grosses Problem sein.
Du installierst z.B. 7zip und hast damit auch die Kommandozeilenversion 7z.exe zum Entpacken.
Verschieben kannst Du mit move, ggfls auch mit kopieren/löschen (z.B. mit rsync oder robocopy).
Das Ganze packst Du in eine kleine Batchdatei, die wird nur wenige Zeilen haben.
Aufgerufen wird das über den Taskplaner , noch schicker geht es mit dem bereits erwähnten Z-Cron.
Alternativ kannst Du natürlich jederzeit das Linux-Subsystem von Windows 10 aktivieren und das mit einem ShellScript lösen, eine weitere Alternative wäre cygwin oder nur die bash davon.
https://helpdeskgeek.com/free-tools-review/5-best-windows-task-scheduler-alternatives/