UNIXwork

Tags

c unix dav shell linux xattr solaris links x11 java rant fun webdav sync gnome apple benchmark network ldap oracle wtf analytics xnedit macos windows graalvm bsd curl mac apache virtualbox rhel zfs sparc tomcat microsoft freebsd arm

xdg-utils

13. Dezember 2019

Unter der Leitung von freedesktop.org wurden einige Teile von Unix-Desktop-Umgebungen vereinheitlicht, unter anderem das Handling von Mime-Typen. Hierfür gibt es die XDG MIME Application specification.

Außerdem gibt es die offiziellen xdg-utils für den Umgang mit Mime-Typen. Mit diesen können unter anderem neue Mime-Typen installiert, Standard-Anwendungen konfiguriert oder Informationen abgefragt werden.

Praktisch im alltäglichen Gebrauch ist xdg-open. Dies öffnet eine Datei mit der dazugehörigen Standard-Anwendung. Dies ist nicht nur hilfreich, wenn man vom Terminal aus deine Datei mit dem passenden grafischen Programm öffnen möchte, sondern kann auch gut in eigenen Programmen verwendet werden, wenn diese externe Programme wie z.B. den Standard-Browser öffnen sollen.

Die xdg-utils dürften bei allen (Unix-)Desktop-Umgebungen dabei sein.

Datenanalyse in der Shell Teil 3: Datei vergleichen

12. Dezember 2019

Mit dem Programm comm können Dateien miteinander verglichen werden. Das Programm prüft, ob Zeilen in Datei1, in Datei2 oder in beiden vorhanden sind. Die Daten müssen hierfür bereits sortiert sein. Falls dies nicht der Fall ist, hilft wieder sort.

Hier ein einfaches Beispiel zu comm:

$ cat > file1
1
2
3
a
b
c
$ cat > file2
0
1
b
c
d
$ comm file1 file2
    	0
            	1
2
3
a
            	b
            	c
    	d

Die Ausgabe enthält 3 Spalten:

  • Spalte 1: Zeilen, die nur in file1 sind
  • Spalte 2: Zeilen, die nur in file2 sind
  • Spalte 3: Zeilen, die in beiden Dateien vorhanden sind

Um die Ausgabe zu filtern, gibt es die Optionen -1 -2 und -3 um die jeweiligen Spalten bei der Ausgabe zu unterdrücken. Um z.B. nur die Spalte 3 auszugeben, muss -12 angegeben werden:

$ comm -12 file1 file2
1
b
c

Damit kann comm genutzt werden, um Schnittmengen oder Differenzmengen zu bilden.

Datenanalyse in der Shell Teil 2: Beispiele

11. Dezember 2019

In Teil 1 habe ich einige Unix-Tools für einfache Datenauswertungen vorgestellt. Dies möchte ich in diesem Artikel mit zwei Beispielen etwas vertiefen.

Dafür habe ich mir ein paar Testdaten von hier besorgt, und zwar die Datei airtravel.csv.

"Month", "1958", "1959", "1960"
"JAN",  340,  360,  417
"FEB",  318,  342,  391
"MAR",  362,  406,  419
"APR",  348,  396,  461
"MAY",  363,  420,  472
"JUN",  435,  472,  535
"JUL",  491,  548,  622
"AUG",  505,  559,  606
"SEP",  404,  463,  508
"OCT",  359,  407,  461
"NOV",  310,  362,  390
"DEC",  337,  405,  432

Diese Beispieldaten enthalten für drei Jahre die monatliche Anzahl an Flugreisenden.

Beispiel 1: Summe von Spalten bilden

Als erstes möchten wir die Gesamtsumme pro Jahr wissen, also die drei Spalten aufsummieren. Um die Daten leichter zu verarbeiten, entfernen wir die Tabellenüberschrift sowie die erste Spalte mit den Monatsbezeichnungen.

$ tail -12 airtravel.csv | cut -d ',' -f 2,3,4 > data1.csv
$ cat data1.csv
  340,  360,  417
  318,  342,  391
  362,  406,  419
  348,  396,  461
  363,  420,  472
  435,  472,  535
  491,  548,  622
  505,  559,  606
  404,  463,  508
  359,  407,  461
  310,  362,  390
  337,  405,  432

Wir summieren wir das jetzt? Hierfür benutzen wir das Programm bc, welcher ein Taschenrechner ist, der seine Eingabe von stdin lesen kann. Um eine vernünftige Eingabe für bc zu generieren, müssen wir alle Zeilen einer Spalte zu einer einzigen Zeile zusammenfügen, getrennt durch ein Plus für die Rechenoperation. Dies kann mit dem Tool paste erledigt werden, in dem die -s Option angegeben wird und mit -d ein Trennzeichen.

Zunächst einmal extrahieren wir mit cut eine Spalte und übergeben diese an paste. Dies liefert eine einzige Zeile mit unseren Zahlen, getrennt durch ein +, welche wir an bc übergeben können, um unsere Summe zu erhalten:

$ cut -d ',' -f 1 data1.csv | paste -s -d+ - | bc
4572

Beispiel 2: Maximum und Minimum finden

Als nächstes möchten wir rausfinden, in welchem Monat es im Jahr 1959 am meisten und am wenigsten Reisende gab. Hierfür schneiden wir wieder die Spaltenüberschriften weg. Danach sortieren wir die gewünschte Spalte und holen uns das Minimum und Maximum mit den Tools head und tail:

$ tail -12 airtravel.csv | cut -d ',' -f 1,3 | sort -t ',' -k 2 > col2_sorted.csv
$ cat col2_sorted.csv
"FEB",  342
"JAN",  360
"NOV",  362
"APR",  396
"DEC",  405
"MAR",  406
"OCT",  407
"MAY",  420
"SEP",  463
"JUN",  472
"JUL",  548
"AUG",  559
$ printf "min: %s\nmax: %s\n" "`head -1 col2_sorted.csv`" "`tail -1 col2_sorted.csv`"
min: "FEB",  342
max: "AUG",  559

Fazit: Einfache Aufgaben sind unproblematisch. Bei komplexeren Anforderungen könnte man aber schnell an die Grenzen stoßen. Das war aber noch nicht alles. Im nächsten Artikel warten weitere Werkzeuge auf uns.

Extended Attributes Teil 10: Windows Syscalls

10. Dezember 2019

Für den Zugriff auf Alternate Data Streams benötigt man unter Windows keine speziellen Syscalls, da die Auswahl des Streams ein Teil des Dateipfades ist. Daher kann man z.B. auch mit fopen oder vermutlich jeder ähnlichen Funktion in anderen Programmiersprachen auf einen anderen Stream zugreifen.

FILE *f = fopen("test.txt:stream2", "w");
fprintf(f, "Hello ADS\n");    
fclose(f);

Was jedoch nicht so einfach geht ist, eine Liste aller Streams einer Datei zu erhalten. Zum Einsatz kommen dabei die Funktionen FindFirstStreamW und FindNextStreamW. Diese funktionieren ähnlich wie die Funktionen zum Auflisten von Verzeichniseinträgen (FindFirstFileW, FindNextFileW). Hier ein Beispiel, wie die Funktionen benutzt werden:

#include <stdio.h>
#include <windows.h>

int main(int argc, char** argv) {

	WIN32_FIND_STREAM_DATA findData;

	HANDLE h = FindFirstStreamW(L"test.txt", FindStreamInfoStandard, &findData, 0);
	if(h == INVALID_HANDLE_VALUE) {
    	return 1;
	}

	do {
    	printf("%S\n", findData.cStreamName);
	} while(FindNextStreamW(h, &findData));

	return 0;
}

Das Format von cStreamName ist :streamname:$streamtype. Streamtype ist in der Regel immer DATA (ich kenne kein Beispiel, in dem dies nicht der Fall ist). Für den Fall, dass die Datei test.txt in dem Beispiel einen zweiten Stream mit dem Namen mystream hat, wäre die Ausgabe folgendermaßen:

::$DATA
:mystream:$DATA

Extended Attributes Teil 9: Windows Commandline Tools

09. Dezember 2019

Windows unterstützt Extended Attributes in Form von Alternate Data Streams (ADS). Ähnlich wie unter Solaris sind Extended Attributes damit keine einfachen Key/Value-Paare, sondern Datei-Streams. Jede Datei hat einen Haupt-Stream mit dem Namen :$DATA. Daneben können aber weitere Streams für eine Datei existieren.

Zugegriffen wird auf ein Attribut bzw. Alternate Data Stream, in dem an den Dateinamen der Stream-Name, getrennt durch einen Doppelpunkt, angehängt wird.

> echo Hello World > test.txt

> type test.txt
Hello World

> echo my attribute value > test.txt:myattribute

> type test.txt:myattribute
my attribute value

Auf den eigentlichen Dateiinhalt kann auch mit dem Stream-Namen :$DATA zugegriffen werde, was auch schon Ursache für Sicherheitslücken war. Den IIS konnte man so austricksen und den Inhalt von ASP-Dateien erhalten, in dem man ::$DATA an die URL angehangen hat.

Da der Stream Teil des Dateipfades ist, kann eigentlich mit jedem beliebigen Programm darauf zugegriffen werden, z.B. auch mit Notepad:

> notepad test.txt:myattribute

Lustigerweise funktioniert dies nicht in den Powershell-Cmdlets. Diese haben jedoch Parameter für den Zugriff auf ADS. Z.B. kann Get-Item alle Streams einer Datei auflisten:

PS D:\> Get-Item -path test.txt -stream *

PSPath        : Microsoft.PowerShell.Core\FileSystem::D:\test.txt::$DATA
PSParentPath  : Microsoft.PowerShell.Core\FileSystem::D:\
PSChildName   : test.txt::$DATA
PSDrive       : D
PSProvider    : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : False
FileName      : D:\test.txt
Stream        : :$DATA
Length        : 14

PSPath        : Microsoft.PowerShell.Core\FileSystem::D:\test.txt:myattribute
PSParentPath  : Microsoft.PowerShell.Core\FileSystem::D:\
PSChildName   : test.txt:myattribute
PSDrive       : D
PSProvider    : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : False
FileName      : D:\test.txt
Stream        : myattribute
Length        : 21
Zurück Weiter