In der Shell Informationen von Dateien auswerten

Aus LinuxUser 01/2020

In der Shell Informationen von Dateien auswerten

© Rawpixel, 123RF

Bestandsaufnahme

Mit den passenden Befehlen werten Sie Informationen über Dateien und Verzeichnisse so aus, dass diese beim Organisieren und Verarbeiten helfen.

In einem Verzeichnis liegen Hunderte oder sogar Tausende Dateien, und Sie möchten Ordnung schaffen. Dabei zeigt sich: Die Dateinamen haben keine einheitliche Endung; ein Kopieren nach dem Muster cp *.txt klappt also nicht. In einem anderen Szenario steht das Datum des letzten Zugriffs im Mittelpunkt – wichtig beim Sichern, in der Forensik sowie beim Verwalten von Versionen.

Anstelle langwieriger Klicks im grafischen Dateimanager hilft ein Shell-Skript mit dem Test-Befehl, wenn es um das Erkennen von Objekten im Dateisystem geht, und der Frage, welche Informationen die Daten darüber hinaus noch hergeben.

Typ bestimmen

Mittels des Befehls file erhalten Sie Informationen über den Inhalt einer Datei. Zusammen mit der Option -i erhalten Sie eine Ausgabe wie in Abbildung 1 gezeigt. Bei der untersuchten Datei handelt es sich um reinen Text. Dateiendungen führen File dabei nicht in die Irre, es kommt auf den Inhalt an (Abbildung 2).

Abbildung 1: Der Befehl <code>file</code> greift beim Erkennen von Inhalten auf eine Liste charakteristischer Muster zur&uuml;ck.

Abbildung 1: Der Befehl file greift beim Erkennen von Inhalten auf eine Liste charakteristischer Muster zurück.

Abbildung 2: Dank der Tests auf die Muster im Inhalt bestimmt File selbst solche Dateien zuverl&auml;ssig, deren Endungen nicht dem tats&auml;chlichen Inhalt entsprechen.

Abbildung 2: Dank der Tests auf die Muster im Inhalt bestimmt File selbst solche Dateien zuverlässig, deren Endungen nicht dem tatsächlichen Inhalt entsprechen.

Das Tool bezieht seine Musterinformationen aus dem Magic-File /usr/share/misc/magic.mgc. Für Spezialfälle erstellen Sie bei Bedarf eine eigene Magic-Datei und übergeben sie File beim Aufruf mit der Option -m Datei. Interessiert Sie speziell der MIME-Typ einer Datei, verwenden Sie die Option --mime-type.

Mit File greifen Sie selbst auf Gerätedateien zu (Abbildung 3) und werten diese aus. Dabei gibt die Software zusätzlich die Major- und Minor-Nummern aus (Abbildung 3). Mit entsprechenden Rechten erhalten Sie Angaben zum Dateisystem (Abbildung 4). Dazu verwenden Sie die Option -s Gerätedatei. Geben Sie hier nur das Gerät für die Festplatte ohne die Nummer für die Partition an, erhalten Sie Angaben unter anderem zur Blockgröße.

Abbildung 3: Rufen Sie die Informationen f&uuml;r eine Ger&auml;tedatei auf, zeigt das Tool File wenn m&ouml;glich Major- und Minor-Nummer.

Abbildung 3: Rufen Sie die Informationen für eine Gerätedatei auf, zeigt das Tool File wenn möglich Major- und Minor-Nummer.

Abbildung 4: Da Ger&auml;te unter Linux sich wie eine Datei verhalten, liefert File zu diesen ebenfalls Informationen.

Abbildung 4: Da Geräte unter Linux sich wie eine Datei verhalten, liefert File zu diesen ebenfalls Informationen.

TIPP

Die Major-Nummer gibt dem Kernel den Treiber für das Gerät an. Die Minor-Nummer hilft dem Treiber, mehrere von ihm verwaltete Geräte zu unterscheiden.

File gibt die Informationen in der Regel in der Form Dateiname: Daten aus. Diesen Umstand machen Sie sich bei Bedarf beim Einsatz in Shell-Skripten zunutze. Verwenden Sie im Skript eine For-Schleife, brauchen Sie eindeutige Dateinamen. Die erhalten Sie durch ls -1. Je Zeile ergibt dies einen Dateinamen. Die Subshell im Schleifenkopf der For-Schleife liefert damit zuverlässige Argumente, solange sich kein Leerzeichen im Dateinamen befindet. Hier müssten Sie vorher den Namen umwandeln oder Anführungszeichen verwenden.

Das Beispiel in Listing 1 zeigt eine Anwendung, die gezielt PDF-Dateien sucht und zur Auswahl anbietet (Abbildung 5). Das dynamische Auswahlmenü entsteht dabei unter Zuhilfenahme von Smenu.

Listing 1

#! /bin/bash
# Vorbelegung Menueausstieg
menu="E-N-D-E"
cd $HOME/Daten
# PDF-Dateien suchen
for i in $(ls -1); do
  file $i | cut -d \: -f2 | grep -q PDF
  if [ $? -eq 0 ]; then
    # Auswahl montieren
    menu=$(echo $menu $i)
  fi
done
# Auswahlmenue mit Smenu und PDF-Anzeige
while true; do
  ausw=$(echo $menu | smenu -n 10 -t1 )
  if [ "$ausw" = "E-N-D-E" ]; then
    exit
  fi
  atril $ausw
  clear
done
Abbildung 5: Mit nur wenigen Zeilen Shellcode sowie dem Tool Smenu erstellen Sie eine einfache Auswahl f&uuml;r einen bestimmten Typ von Dateien.

Abbildung 5: Mit nur wenigen Zeilen Shellcode sowie dem Tool Smenu erstellen Sie eine einfache Auswahl für einen bestimmten Typ von Dateien.

Statusinformationen

Zu den mit dem Befehl stat auslesbaren Informationen über Dateien und Verzeichnisse gehört mehr oder weniger alles, was Sie auch mit Ls erhalten. Ohne Angabe einer weiteren Option erhalten Sie alle Daten über eine Datei aufgelistet. Abbildung 6 stellt auch gleich die Auswirkung eines Lesezugriffs dar. Beachten Sie hierbei die Zeile Zugriff mit den Datum- und Uhrzeitangaben. Allerdings funktioniert genau dies nicht bei mit der Option noatime eingehängten Dateisystemen. Damit wird der Datenzugriff beschleunigt, weil das Dateisystem nicht bei jedem Lesezugriff einen Eintrag vornehmen muss.

Abbildung 6: Ohne Angabe von Optionen enth&auml;lt die Ausgabe von Stat eine Vielzahl von Informationen.

Abbildung 6: Ohne Angabe von Optionen enthält die Ausgabe von Stat eine Vielzahl von Informationen.

Mittels stat -c Format lesen Sie gezielt einzelne Informationen über eine Datei (oder ein Dateisystem) aus und werten diese in einem Skript aus. Die Tabelle “Stat-Formatangaben” führt die wichtigsten Möglichkeiten auf. Abbildung 7 zeigt einige Aufrufe, unter anderem die Abfrage der Zugriffsrechte in numerischer Form. Diese Information eignet sich unter Umständen für ein Installationsskript.

Anweisung

Angabe

%a

Zugriffsrechte in numerischer Form

%A

Zugriffsrechte in ausführlicher Form

%d

Gerätenummer (dezimal) für Gerätedatei

%t

Major-Nummer Gerätedatei (Hexadezimal)

%T

Minor-Nummer Gerätedatei (Hexadezimal)

%F

Dateityp

%m

Dateisystem, in dem sich die Datei befindet

%u

UID des Besitzers

%U

Benutzername des Besitzers

%g

GID

%G

Gruppenname

%x

letzter Lesezugriff (Klartext)

%X

letzter Lesezugriff (Unix-Sekunden)

%y

letzte Änderung (Klartext)

%Y

letzte Änderung (Unix-Sekunden)

%z

letzter Zugriff (Klartext)

%Z

letzter Zugriff (Unix-Sekunden)

Abbildung 7: Einige Beispiele f&uuml;r formatierte Stat-Abfragen.

Abbildung 7: Einige Beispiele für formatierte Stat-Abfragen.

Beachten Sie dabei, dass die deutschsprachige Ausgabe von Stat stellenweise etwas mehrdeutig ausfällt: So meint etwa Zugriff den letzten lesenden Zugriff, wobei Sie aber beachten sollten, dass Mount-Optionen wie noatime diesen Wert beeinflussen. Der Begriff Modifiziert bezieht sich auf den Inhalt der Datei, enthält also unter Umständen das Erstellungsdatum, immer aber den letzten Schreibzugriff. Bei Geändert sehen Sie Angaben zum Ändern der Zugriffsrechte, des Eigentümers oder Ähnliches. Den Wert für Geburt ermittelt Stat unter Linux derzeit wegen eines Programmfehlers nicht.

Listing 2 zeigt ein kleines Skript, das die Zugriffsrechte einer Datei ausliest und anschließend ändert, falls sie zu lax ausfallen. Es ruft das Kommando zum Ändern der Rechte mit der Option -v auf, sodass Sie im Terminal sehen, was es tut. Abbildung 8 zeigt die Datenbasis dazu, Abbildung 9 den Durchlauf des Skripts.

Listing 2

#! /bin/bash
# $1 als Verzeichnis setzen,
# sonst Abbruch
if [ -z $1 ]; then
  exit
fi
# Wechsle ins Verzeichnis
cd $1
for i in $(ls -1); do
  # Zugriffsrechte auswerten
  stat -c %a $i | grep -q 75
  if [ $? -eq 0 ]; then
    # Aendern, wenn Gruppe
    # oder Rest die Datei
    # ausfuehren duerften.
    chmod -v 700 $i
  fi
done
Abbildung 8: Zu lax gesetzte Rechte auf Dateien gew&auml;hren Unbefugten unter Umst&auml;nden Einblick in die Daten.

Abbildung 8: Zu lax gesetzte Rechte auf Dateien gewähren Unbefugten unter Umständen Einblick in die Daten.

Abbildung 9: Der Ablauf des Shell-Skripts aus <a href="#artRef-l2">Listing&nbsp;2</a> und die Anzeige der ge&auml;nderten Dateien.

Abbildung 9: Der Ablauf des Shell-Skripts aus Listing 2 und die Anzeige der geänderten Dateien.

Zeitstempel ändern

Normalerweise modifizieren Anwendungen, die mit der betroffenen Datei arbeiten, die Informationen in den Zeitstempeln. Von Hand gelingt das mit dem Kommando touch (siehe Tabelle “Touch-Optionen”). Wenn Sie Touch mit einem nicht existierenden Dateinamen ausführen, legt das System einen entsprechenden Eintrag ins Dateisystem vor, legt also eine Datei ohne Inhalt an. Rufen Sie touch Datei ohne Optionen auf, dann aktualisiert das Programm alle Zeitstempel der Datei auf die Systemzeit.

Option

Aktion

-a

Zugriffszeit ändern

-m

Modifikationszeit ändern

-t Zeit

Zeit statt Systemzeit verwenden

-r Datei

Angabe einer Referenzdatei, von der Touch die Zeitstempel übernimmt

Die Zeitangabe für die Option -t erfolgt in der Form MMTThhmm. Sie dürfen die Angabe zusätzlich um das Kalenderjahr und die Sekunden erweitern: JJMMTThhmm.ss. Abbildung 10 zeigt das Ändern der Zugriffszeit mithilfe von Touch. In Abbildung 11 sehen Sie ein Beispiel für das Referenzieren über eine bestehende Datei. Sie erkennen in der folgenden Ausgabe des Kommandos stat das besondere Datum für den Zugriff, das der Befehl in Abbildung 10 gesetzt hat.

Abbildung 10: Einsatz von Touch erm&ouml;glicht es, den Zeitstempel einer Datei zu ver&auml;ndern.

Abbildung 10: Einsatz von Touch ermöglicht es, den Zeitstempel einer Datei zu verändern.

Abbildung 11: Ein Beispiel f&uuml;r die &Uuml;bernahme des Zeitstempels von einer Referenzdatei.

Abbildung 11: Ein Beispiel für die Übernahme des Zeitstempels von einer Referenzdatei.

Dateien testen

Das Test-Kommando kommt meist nicht ausgeschrieben zum Einsatz, sondern in der Notation mit eckigen Klammern und entsprechenden Optionen (Listing 3). Es dient zum Auswerten der Art und der Zeitstempel von Objekten im Verzeichnisbaum. Dabei liefert es einen Rückgabewert von 0, wenn die getestete Kondition zutrifft (“wahr”). Die Tabelle “Test-Optionen” listet einige Möglichkeiten auf.

Listing 3

if [ $? -eq 0 ];
# ist dasselbe wie
if test $? -eq 0;

Test

wahr, wenn …

-e Objekt

Objekt existiert

wahr, falls das Objekt existiert und …

-b Objekt

eine Blockgerätedatei ist

-c Objekt

eine Zeichengerätedatei ist

-d Objekt

ein Verzeichnis ist

-f Objekt

eine gewöhnliche Datei ist

-g Objekt

das Gruppen-ID-Bit gesetzt ist

-G Objekt

der Gruppeneintrag von Prozess und Datei übereinstimmen

-h Objekt

ein symbolischer Link ist

-k Objekt

das Sticky-Bit gesetzt ist

-L Objekt

ein symbolischer Link ist

-O Objekt

der Abfrageprozess denselben Eigentümer aufweist

-p Objekt

ein FIFO ist

-r Objekt

lesbar ist

-s Objekt

dessen Größe nicht 0 ist

-S Objekt

ein Socket ist

-u Objekt

das UID-Bit gesetzt ist

-w Objekt

schreibbar ist

-x Objekt

ausführbar ist

wahr, wenn Objekt1 existiert und …

Objekt1 -ef Objekt2

Objekt2 sich auf dasselbe Objekt bezieht

Objekt1 -nt Objekt2

neuer als Objekt2 ist

Objekt1 -ot Objekt2

älter als Objekt2 ist

Der Befehl test bietet sich etwa an, um in einem If-Konstrukt eine Unterscheidung zu treffen. Der Einsatzbereich fällt dabei umfangreich aus. In einem Skript zum Sichern von Daten wäre es beispielsweise möglich, zu prüfen, ob die Datei DASI.INFO existiert. Falls ja, erstellt das Skript eine Kopie von allen Dateien, die neuer als der Zeitstempel dieser Datei sind. Anderenfalls nimmt das Skript eine Komplettsicherung vor.

Listing 4 zeigt den Code für ein Skript, das ein Verzeichnis namens DASITEST anlegt, falls es nicht existiert – eine alltägliche Angelegenheit, die Sie auf diese Weise schnell erledigen (Abbildung 12).

Listing 4

#! /bin/bash
uvzneu () {
  # DATEI?
  if [ -f DASITEST ]; then
    read -p "Datei mit gleichem Namen vorhanden! Umbenennen (j)? " we
    if [ "$we" = "j" ]; then
      mv DASITEST DASITEST.datei
    else
      echo "Die Datei DASITEST entweder löschen oder verschieben!"
      echo "SKRIPTENDE"
    fi
  fi
  if [ -d DASITEST ]; then
    cd DASITEST
    echo -n "Ich befinde mich im Verzeichnis $PWD"
    echo " "
  else
    echo "Anlegen DASITEST"
    mkdir DASITEST
  fi
  return 0
}
uvzneu
Abbildung 12: Das Skript &uuml;bernimmt Aufgaben, die Sie automatisch schneller und zuverl&auml;ssiger erledigen.

Abbildung 12: Das Skript übernimmt Aufgaben, die Sie automatisch schneller und zuverlässiger erledigen.

Zeitstempel und Rechte

Das Werkzeug Find sucht nicht nur nach Namen von Dateien und Verzeichnissen, sondern bezieht bei Bedarf Zeitstempel, Zugriffsrechte und die Dateigröße als Filter mit ein. Um sich mit dem vollen Umfang dieses Befehls vertraut zu machen, werfen Sie am besten einen Blick auf die Manpage. Die Tabelle “Find-Optionen” führt die wichtigsten Möglichkeiten auf.

Aktion

Option

Hinweis

-type Typ

nach Typ suchen

-size +/-Größe

nach Größe suchen

– = Höchstgröße, + = Mindestgröße, ohne = gleich

-perm Dateirechte

nach Zugriffsrechten suchen

-newer Datei

Dateien neuer als Datei suchen

-mtime -/+N

Dateien suchen, die seit N Tagen nicht geändert wurden

+ = mindestens, - = innerhalb

-atime -/+N

Dateien suchen, auf die seit N Tage nicht zugegriffen wurde

+ = mindestens, - = innerhalb

-execdir Befehl "{}" +

für gefundene Datei Befehl ausführen

sicherere Methode

Die Ausgabe von Find leiten Sie bei Bedarf an eine Pipe weiter oder verarbeiten sie mittels Xargs weiter, das das Ergebnis an weitere Befehle durchreicht, wie etwa Tar. Als Beispiel legt Listing 5 für Dateien je nach deren Änderungsdatum Unterverzeichnisse an und verschiebt sie dorthin. Abbildung 13 zeigt die Ausgangslage, Abbildung 14 den Durchlauf und Abbildung 15 schließlich das Ergebnis.

Listing 5

#!/bin/bash
# $1 = zu bearbeitendes Verzeichnis
if [ -z $1 ]; then
  echo "Keine Eingabe"
  exit
fi
cd $1
for i in $(stat -c %y:%n * | sort -r | tr \  \:); do
  # Variablen uvz (Unterverzeichnis)
  # und dn (Dateiname) belegen
  uvz=$(echo $i | cut -d \: -f1)
  dn=$(echo $i | cut -d \: -f6)
  # Falls Verzeichnis, nicht bearbeiten
  # und Schleifendurchlauf neu beginnen
  if [ -d $dn ]; then
    echo "$dn: Verzeichnis, wird ausgelassen"
    continue
  fi
  # uvz gegebenenfalls anlegen und
  # Datei nach dort verschieben
  if [ -d $uvz ]; then
    mv -v $dn $uvz
  else
    mkdir $uvz
    mv -v $dn $uvz
  fi
done
Abbildung 13: Der Verzeichnisinhalt vor dem Durchlauf des Skripts.

Abbildung 13: Der Verzeichnisinhalt vor dem Durchlauf des Skripts.

Abbildung 14: Ein Skript, das die Metadaten der Dateien auswertet, sortiert diese in eine entsprechende Struktur.

Abbildung 14: Ein Skript, das die Metadaten der Dateien auswertet, sortiert diese in eine entsprechende Struktur.

Abbildung 15: In der neuen Verzeichnisstruktur landen die Dateien in entsprechenden Unterverzeichnissen.

Abbildung 15: In der neuen Verzeichnisstruktur landen die Dateien in entsprechenden Unterverzeichnissen.

Die For-Schleife erhält die Daten mittels Stat. Da Leerzeichen als Trenner dienen, ersetzt es diese durch Doppelpunkte. Die Ausgabe erfolgt nach Datum sortiert, beginnend mit den neuesten Dateien.

In der Schleife enthält die Variable uvz das anzulegende Unterverzeichnis, dn nimmt den Dateinamen auf. Dabei wertet das Skript aus, ob es sich bei dn um ein Verzeichnis handelt, und bricht in diesem Fall die Bearbeitung ab. Die Schleife beginnt dann mit einem neuen Durchlauf. Das verhindert, dass das Skript ein Verzeichnis bearbeitet.

Handelt es sich bei dn dagegen um eine Datei, kontrolliert die Routine anschließend wiederum mittels Test, ob das Unterverzeichnis bereits besteht. Ist das nicht der Fall, legt es den Ordner an und verschiebt anschließend die Datei dorthin. Besteht das Verzeichnis bereits, beschränkt es sich auf Letzteres. Eine optische Kontrolle liefert Tree (Abbildung 15).

Fazit

Mit den geeigneten Shell-Kommandos können Sie verschiedene Eigenschaften von Dateien und Verzeichnissen erkennen, auswerten und ändern. Auf diese Weise lassen sich viele Vorgänge durch Skripte vereinfachen. Das vermeidet gegenüber Klickorgien im Dateimanager Fehler und spart wertvolle Zeit.

Der Autor

Harald Zisler beschäftigt sich seit den frühen 90er-Jahren mit FreeBSD und Linux. Zu Technik- und EDV-Themen verfasst er Bücher und Beiträge für Zeitschriften.

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDF
LinuxUser 01/2020 KAUFEN
EINZELNE AUSGABE
ABONNEMENTS
TABLET & SMARTPHONE APPS
E-Mail Benachrichtigung
Benachrichtige mich zu:

Hinweis: Dieser Artikel ist älter als ein Jahr, enthaltene Informationen sind möglicherweise veraltet.

0 Kommentare
Älteste
Neuste Beste Bewertung
Nach oben