Archive for März 2019

Weitere Erkenntnisse zu Tar unter Windows 10

25 März 2019

In diesem Artikel bin ich schon auf TAR.EXE unter Windows 10 eingegangen: https://newyear2006.wordpress.com/2018/10/21/tar-exe-unter-windows-10-der-neue-tausendsassa/. Nun habe ich weitere Erkenntnisse und diese möchte ich in diesem Artikel beschreiben. Dies wird sicher nicht der letzte Artikel zu diesem Thema sein, denn es gibt noch einiges zu entdecken bzw. es gibt noch die eine oder andere Ungereimtheit aber dazu ein anderes Mal mehr.

Genereller Hinweis:

Da macht man sich Mühe und testet alles durch, danach ladet man den Artikel hoch doch dann grätscht WordPress rein und zerhaut einem die mühsam hinterlegte Formatierung Sad smile. Also überall wo in diesem Artikel ein langer Bindestrich steht sollten eigentlich zwei Minuszeichen stehen. Also Hirn einschalten beim Copy und Paste…

Kurze und lange Parameterangaben
Tar kennt kurze wie lange Parameter, z. B. sind diese alle drei Zeilen identisch:

tar -caf test.zip *

tar -c –a -f test.zip *

tar –create –auto-compress –file test.zip *

Teilweise findet man im Internet Beispiele wo tar anstatt mit dem Parameter -caf  einfach nur mit caf, also so angegeben wird, auch dies ist zulässig:

tar caf test.zip *

Nicht direkt aber dennoch auch von Bedeutung ist die Angabe von Parametern mit Gleichheitszeichen, so sind diese beiden Aufruf identisch:

tar –format=7zip –options=7zip:compression=STORE -cf ..\testNeu.7z *

tar –format 7zip –options 7zip:compression=STORE -cf ..\testNeu.7z *

Tar ist so schlau und erkennt die einzelnen Parameter und kann sie problemlos auseinanderhalten, selbst wenn doppelte Gleichheitszeichen wie im zweiten Beispiel angegeben sind.

Einfaches Erzeugen von ZIP-Dateien
Die einfachste Variante ein ZIP-Archiv zu erstellen ist, indem man tar automatisch anweist die Dateiendung zu analysieren um daraus auf das zu verwendende Format zu schließen, dazu gibt man den Parameter a mit an:

tar.exe -caf test.zip *

Unterverzeichnisse ausschließen
Gibt man keinen speziellen Parameter an, werden alle Dateien inklusive deren Unterverzeichnisse gesichert bzw. zurückgespielt. Man kann dieses Verhalten ändern indem man den Parameter -n bzw. die Langform –norecurse bzw. –no-recursion verwendet. Aber nicht erschrecken, obwohl man diesen Parameter angegeben hat wird der eigentlich Verzeichnisname mitgesichert, nur der Inhalt darunter liegenden Dateien nicht!

tar.exe -cnaf test.zip *

Obige Zeile erzeugt also eine ZIP-Datei ohne die Unterverzeichnisinhalte mit zu nehmen.

Groß-/Kleinschreibung ist ein Problem
BSDtar kommt aus der Unix-Welt und da ist die Groß-/Kleinschreibung wichtig! D. h. testex.txt, Testex.txt und z. B. TESTEX.TXT sind alles unterschiedliche Dateien.

Dies wirkt sich auch an unerwarteter Stelle aus, wenn man obiges Beispiel zum Erzeugen einer ZIP-Datei z. B. so schreibt:

tar.exe -caf test.ZIP *

so erhält man keine ZIP-Datei! Statt dessen wird ein konventionelles Tar-Archiv erzeugt.

Ausschließen von Dateien
Sollen bestimmte Dateien nicht gesichert werden dann kann man diese mit dem Parameter –exclude angeben. Exclude kann auch mehrfach angegeben werden, ja muss in Einzelfällen sogar mehrfach angegeben werden, wenn man z. B. im Vorfeld nicht weiß, ob der Dateinamen groß- oder kleingeschrieben wurde.

Am sichersten verwendet man diese drei Varianten, wobei es sicher noch Fälle gibt, wo es nicht klappt:

tar.exe –exclude testex.txt –exclude Testex.txt –exclude TESTEX.TXT -caf test.zip test*

Unter GNU-Tar gibt es den tollen Parameter –ignore-case, doch leider funktioniert dieser bei BSDtar nicht:

tar –ignore-case –exclude testex.txt -caf test.zip test*
tar.exe: Option –ignore-case is not supported

Natürlich wird der Aufruf dadurch schnell unübersichtlich, zum Glück gibt es den Parameter –exclude-from welcher die Angabe eines Dateinamens erlaubt. Mit Powershell kann man dann z. B. sowas machen:

"testex.txt","Testex.txt","TESTEX.TXT" | set-content -Path exclude.txt
tar.exe –exclude-from exclude.txt  -caf test.zip test*

Verhinderung unnötiger Meldung
Manchmal muss man ein Archiv in genau dem Verzeichnis erstellen, welches man sichern möchte. Wenn man alles ohne Ausnahme sichert, dann versucht tar das eigene Archiv nochmals mit zu sichern. Dies wird erkannt und durch folgende Meldung quittiert:

tar.exe -caf Sicherung.zip *
tar.exe: Couldn’t open Sicherung.zip: Permission denied
tar.exe: Error exit delayed from previous errors.

Das Archiv wird trotzdem erstellt, also kein Problem. Sieht halt nur unschön aus. Das Thema kann über einen Aufruf über Powershell und dem expliziten Ausschließen des Archivnamens verhindert werden:

$archive=’Sicherung.zip‘; tar.exe –exclude=$archive -caf $archive *

Verwendung von Optionen
Jedes Format welches von Tar unterstützt wird kennt seine eigenen Optionen. Optionen werden immer eingeleitet durch den Parameter –options. Gibt man Optionen speziell für ein bestimmtes Format an, so gibt man den Formatnamen z. B. zip gefolgt von einem Doppelpunkt und dann dem eigentlichen Optionsparameter. Dadurch kann man bei ZIP-Dateien den Kompressionsfaktor angeben. So erzeugt diese Option die höchste Kompression, Standard ist anscheinend 6, welches von der ZLib-Bibliothek vorgegeben ist.

–options zip:compression-level=9

Weiß man, dass man in einem Archiv mehr als 4GB an Daten speichern muss, kann man gleich den Parameter für die Zip64-Unterstützung angeben:

–options zip:zip64

Will man das ZIP-Archiv schützen, dann kann man noch eine Verschlüsselung mitangeben, es werden drei Varianten unterstützt:

–options zip:encryption=zipcrypt

–options zip:encryption=aes128

–options zip:encryption=aes256

Komplett könnte ein Aufruf also so aussehen:

tar.exe –format=zip –options zip:zip64 –options zip:encryption=aes256 –passphrase=MeinPassword -cf test.zip *

7Zip-Unterstützung
Tar unterstützt eigentlich 7Zip, wenn man jedoch eine 7Zip-Datei versucht zu entpacken, dann passiert folgendes:

tar -xvf .\test.7z
x test.txt: LZMA codec is unsupported
tar.exe: Error exit delayed from previous errors.

Trotzdem kann aber Tar das Verzeichnis des Archivs auflisten:

tar -tvf .\test.7z
-rw-rw-rw-  0 0      0           7 Mrz 25 09:26 test.txt

Man könnte nun sagen, ok vielleicht klappt es nicht mit LZMA aber es gibt ja noch LZMA2, doch leider:

tar -c –format 7zip –options 7zip:compression=lzma1 -f .\test.7z test.txt
tar.exe: `lzma1′ compression not supported on this platform
tar -c –format 7zip –options 7zip:compression=lzma2 -f .\test.7z test.txt
tar.exe: `lzma2′ compression not supported on this platform

Als Bestätigung, dass der Parameter korrekt angegeben wurde, kann man einfach etwas unsinniges angeben:

tar -c –format 7zip –options 7zip:compression=lzma3 -f .\test.7z test.txt
tar.exe: Unknown compression name: `lzma3′

Also müssen wir davon ausgehen, dass Microsoft das zugehörige lzma-Modul für hochwertige Kompression von 7Zip-Dateien nicht mit eingebaut hat. Schade.

Man kann jedoch problemlos 7Zip-Dateien erstellen, diese sind dann allerdings nicht hochgradig komprimiert sondern nur mit einem einfachen Deflate-Algorithmus gestaucht.

TAR.exe Rückgabe von Fehlercode
Tar.exe gibt immer einen Errorlevel zurück, unter Powershell kann dieser mittels $LastExitCode ganz einfach abgefragt werden. Ist dieser 0 war die Abfrage erfolgreich, ist er 1 trat ein Fehler auf.

Parameter –fast-read
Der Parameter –fast-read macht auf den ersten Blick keinen Sinn, denn er sorgt dafür, dass die weitere Verarbeitung eines Archivs gleich gestoppt wird.

Dieser Parameter ist aber nützlich um schnell eine Information über ein Archiv zu erhalten ohne es komplett verarbeiten zu müssen. Vor allem bei großen Archiven sorgt dies für eine enorme Zeitersparnis.

Möchte man also nur wissen, ob eine bestimmte Datei enthalten ist, ruft man

tar.exe –fast-read -tf archiv Datei

auf und fragt den $LastExitCode ab.

Anwendung bei .CAB-Dateien
Unter Windows hat man es ab und an mit .CAB-Dateien zu tun, welche z. B. für Updates benötigt werden. Seither musste man mit dem Befehl Expand.exe arbeiten, alternativ kann man nun tar.exe verwenden. So sind diese beiden Aufrufe identisch, sie geben beide den Inhalt des Archivs aus:

expand.exe -D  CabDatei.CAB
tar -tvf CabDatei.CAB

Man kann zwar CAB-Dateien entpacken, allerdings nicht mit tar.exe packen, denn tar kann nur lesend auf CAB-Dateien zugreifen!

Wildcards bzw. Patterns
Man kann bei den Verzeichnis- und Dateinamenparametern wie –exclude auch Wildcards angeben, diese richten sich nach den “Filename substitution”-Richtlinien aus https://www.freebsd.org/cgi/man.cgi?query=tcsh. Es sind zwar keine vollständigen RegEx-Ausdrücke möglich aber Angaben wie

Zur Vereinfachung zur Erzeugung der nötigen Patterns kann man diese Funktion verwenden:

Function New-GKPattern ($String) { (($String.ToLower().tochararray()) | % {$t=[System.Convert]::ToString($_); If ($t.ToLower() -ceq $t.ToUpper()) {$t} else {"[$($t.ToLower())$($t.ToUpper())]"}}) -join “}

Die Funktion macht aus

New-GKPattern "Agent§$%"

den String "[aA][gG][eE][nN][tT]§$%", jeder Buchstabe wird als groß und klein angegeben, Zeichen oder Buchstaben wie ß wo es keine unterschiedliche Schreibweise gibt, werden direkt übernommen.

Mit dieser Methode könnte man obiges Beispiel wo der exclude-Parameter beschrieben war so verwenden:

tar.exe –exclude $(New-GKPattern ‚testex.txt‘)  -caf test.zip test*

Verwendung unter WinPE und WinRE
Man kann Tar direkt unter WindowsPE kurz WinPE bzw. im Windows Recovery Environment kurz WinRE verwenden. Doch leider ist Tar in diesem Umgebungen nicht direkt enthalten (Stand 1903, Build 18361). Man kann allerdings von einer anderen Windows 10 (64-Bit) Maschine aus dem Verzeichnis C:\Windows\System32 die Dateien tar.exe sowie archiveint.dll kopieren um Tar wie gewohnt verwenden zu können. Übrigens kann man auch curl.exe gleich mitnehmen, dies könnte in bestimmten Situationen auch hilfreich sein. Bei curl.exe scheint es keine weiteren Abhängigkeiten zu geben.

Weitere Infos zu Tar
Möchte man etwas speziell über Möglichkeiten von Tar.EXE wissen, dann ist ein Blick in den Sourcecode hilfreich. Man holt sich einfach die Version durch

tar –version

und geht mit der libarchive Version auf ein definiertes Tag z. B.

https://github.com/libarchive/libarchive/tree/v3.3.2

Oder automatisiert:

$version = (((tar.exe –version) -split ‚-‚)[1] -split ‚ ‚)[2]
start "https://github.com/libarchive/libarchive/tree/v$version"