Skip to content

6 Dateien Aufzucht und Pflege

6 Dateien: Aufzucht und Pflege

Lernziele

  • Die Linux-Konventionen über Datei und Verzeichnisnamen kennen

  • Die wichtigsten Kommandos zum Umgang mit Dateien und Verzeichnissen beherrschen

  • Mit Suchmustern in der Shell umgehen können

Vorkenntnisse

  • Arbeit mit der Shell

  • Umgang mit einem Texteditor (siehe Kapitel 3)

6.1 Datei undPfadnamen

6.1.1 Dateinamen

Zu den wesentlichen Diensten eines Betriebssystems wie Linux gehört es, Daten auf dauerhaften Speichermedien wie Festplatten oder USB-Sticks zu speichern und sie später wiederzufinden. Um dies für Menschen erträglich zu gestalten, werden zusammengehörende Daten normalerweise zu „Dateien” zusammengefasst und auf dem Speichermedium unter einem Namen gespeichert.

💡 Auch wenn Ihnen das trivial vorkommen mag: Selbstverständlich ist das nicht. In früheren Zeiten mussten Nutzer:innen mitunter die passenden Spurennummern auf Platten kennen, um ihre Daten wiederzufinden.

Bevor wir Ihnen zeigen können, wie Sie mit Dateien umgehen, müssen wir Ihnen zunächst erklären, wie Linux Dateien benennt.

In Linux-Dateinamen sind grundsätzlich alle Zeichen zugelassen, die der Computer darstellen kann (und noch einige mehr). Da einige dieser Zeichen jedoch eine besondere Bedeutung haben, raten wir von deren Verwendung in Dateinamen ab. Innerhalb von Dateinamen sind nur zwei Zeichen komplett verboten: der Schrägstrich und das Nullbyte (das Zeichen mit dem ASCII-Wert 0). Andere Zeichen wie Leerzeichen, Umlaute oder Dollarzeichen können verwendet werden, müssen dann auf der Kommandozeile aber meist durch einen Rückstrich oder Anführungszeichen maskiert werden, um Fehlinterpretationen durch die Shell zu vermeiden.

⚠️ Für Umsteiger ist es weiterhin eine Stolperfalle, dass Linux in Dateinamen zwischen Groß- und Kleinschreibung unterscheidet. Im Gegensatz zu Windows, wo Groß- und Kleinschreibung in Dateinamen zwar dargestellt, aber identisch behandelt werden, interpretiert Linux „x-files” und „X-Files” tatsächlich als zwei verschiedene Dateinamen.

Dateinamen dürfen unter Linux bis zu 255 Zeichen lang sein, aber die maximale Pfadlänge (inkl. Verzeichnisse) kann je nach Dateisystem und Konfiguration variieren. Für maximale Kompatibilität (z. B. mit Windows oder FAT32) sollten Dateinamen und Pfade kürzer als 255 Zeichen sein. Umlaute und Sonderzeichen sind zwar möglich, können aber zu Problemen führen, wenn Dateien auf anderen Systemen genutzt werden sollen. Da ein solcher Name auf einem normalen Textterminal gut drei Zeilen einnehmen würde, sollte dies Ihren Stil jedoch nicht übermäßig einschränken.

Eine weitere Abweichung zu DOS- bzw. Windows-Rechnern besteht darin, dass Dateien unter Linux nicht durch entsprechende Endungen charakterisiert werden müssen. Der Punkt ist in einem Dateinamen also ein ganz gewöhnliches Zeichen. Ein Text kann daher als „blabla.txt” abgespeichert werden, aber „blabla” wäre grundsätzlich ebenso zulässig. Das heißt allerdings nicht, dass Sie keine „Dateiendungen” benutzen sollten, denn solche Kennzeichnungen erleichtern die Identifizierung des Dateiinhaltes.

💡 Manche Programme bestehen darauf, dass ihre Eingabedateien bestimmte Endungen haben. Der C-Compiler GCC betrachtet beispielsweise Dateien mit der Endung „.c” als C-Quelltext, Dateien mit der Endung „.s” als Assemblerquelltext und Dateien mit der Endung „.o” als vorübersetzte Objektdateien.

Umlaute und andere Sonderzeichen können Sie in Dateinamen grundsätzlich verwenden. Für maximale Portabilität (z. B. mit Windows oder FAT32) sollten Sie jedoch auf Sonderzeichen verzichten, da nicht garantiert ist, dass sie auf anderen Systemen korrekt dargestellt werden.

⚠️ Was mit Sonderzeichen passiert, hängt von der Zeichencodierung (z. B. UTF-8) und der Ortseinstellung ab. UTF-8 ist heute der De-facto-Standard unter Linux und unterstützt alle Unicode-Zeichen. Dennoch können Probleme auftreten, wenn Dateien auf Systemen mit anderen Codierungen (z. B. ISO 8859-1) genutzt werden.

💡 Sollten Sie jemals Dateinamen mit falscher Zeichencodierung vorfinden, kann Ihnen das Programm convmv helfen. Es konvertiert Dateinamen zwischen verschiedenen Zeichencodierungen. Das Programm ist in den Repositories der meisten Distributionen verfügbar, muss aber ggf. nachinstalliert werden. Allerdings sollten Sie sich erst damit befassen, wenn Sie den Rest dieses Kapitels durchgearbeitet haben, denn wir haben Ihnen noch nicht einmal das reguläre mv erklärt.

Ohne Bedenken lassen sich alle Zeichen aus

ABCDEFGHIJKLMNOPQRSTUVWXYZ
abcdefghijklmnopqrstuvwxyz
0123456789+-._

In Dateinamen sollten Sie die folgenden Tipps berücksichtigen: Allerdings sollten Sie die folgenden Tipps berücksichtigen:

  • Um den Datenaustausch mit älteren Unix-Systemen zu ermöglichen, sollte die Länge eines Dateinamens maximal 14 Zeichen betragen.

  • Dateinamen sollten stets mit einem der genannten Buchstaben oder einer Ziffer beginnen. Die vier anderen Zeichen sind nur innerhalb eines Dateinamens problemlos verwendbar.

Diese Konventionen lassen sich am leichtesten mit ein paar Beispielen verstehen. Zulässige Dateinamen wären etwa:

X-files bla.txt.bak 17.Juni 7_of_9

Schwierigkeiten wären dagegen möglich (wenn nicht sogar wahrscheinlich oder gar sicher) mit:

-20°C # Beginnt mit »-«, Sonderzeichen
.profile # Wird versteckt
3/4-Takt # Enthält verbotenes Zeichen
Müll # Enthält Umlaut

Eine weitere Besonderheit ist, dass Dateinamen, die mit einem Punkt beginnen, an einigen Stellen – etwa beim Auflisten von Verzeichnisinhalten – übersprungen werden. Dateien mit solchen Namen gelten als „versteckt”. Diese Eigenschaft wird unter anderem gerne für Dateien verwendet, die Voreinstellungen für Programme enthalten und in Dateinamenslisten nicht von wichtigeren Dateien ablenken sollen.

💡 Für DOS- und Windows-Experten: Diese Systeme erlauben „versteckte” Dateien über ein unabhängig vom Namen zu setzendes „Dateiattribut”. Unter Linux bzw. Unix gibt es so etwas nicht.

6.1.2 Verzeichnisse

Da auf demselben Linux-System potenziell viele Benutzer arbeiten können, wäre es problematisch, wenn es jeden Dateinamen nur einmal geben dürfte. Benutzer wie Hugo könnten nur schwer verstehen, warum sie keine Datei namens brief.txt anlegen können, nur weil die Benutzerin Susi schon eine Datei mit dem gleichen Namen hat. Außerdem muss irgendwie geregelt werden, dass Hugo nicht alle Dateien von Susi lesen kann und umgekehrt.

Aus diesem Grund unterstützt Linux das Konzept hierarchischer Verzeichnisse, die zum Gruppieren von Dateien dienen. Dateinamen müssen nicht über das ganze System hinweg eindeutig sein, sondern nur innerhalb desselben Verzeichnisses. Das bedeutet, dass Hugo und Susi vom System verschiedene Verzeichnisse zugeordnet bekommen und darin ihre Dateien jeweils nach Belieben benennen können, ohne aufeinander Rücksicht nehmen zu müssen. Ferner kann man Hugo den Zugriff auf Susis Verzeichnis verbieten (und umgekehrt), sodass man sich nicht mehr um die einzelnen Dateien kümmern muss, die sich darin befinden.

Auch Verzeichnisse sind bei Linux Dateien, wenn auch solche, die sich nicht mit denselben Mitteln bearbeiten lassen wie „gewöhnliche“ Dateien. Das bedeutet jedoch, dass für die Namen von Verzeichnissen dieselben Regeln gelten wie für die Namen von Dateien (siehe vorheriger Abschnitt). Sie müssen nur noch wissen, dass der Schrägstrich („/”) dazu dient, Dateinamen von Verzeichnisnamen zu trennen. hugo/brief.txt wäre also die Datei brief.txt im Verzeichnis hugo.

Verzeichnisse können andere Verzeichnisse enthalten (das ist das „hierarchisch” von weiter vorne), wodurch sich eine baumartige Struktur ergibt, die auch als „Verzeichnisbaum” bezeichnet wird. Ein Linux-System hat ein spezielles Verzeichnis, das die Wurzel des Baums bildet und deswegen „Wurzelverzeichnis” oder englisch „root directory” genannt wird. Es hat nach Konvention den Namen „/” (Schrägstrich).

💡 Trotz seiner englischen Bezeichnung hat das Wurzelverzeichnis nichts mit dem Systemverwalter root zu tun. Die beiden heißen einfach nur ähnlich.

💡 Der Schrägstrich spielt hier eine Doppelrolle: Einerseits dient er als Name des Wurzelverzeichnisses, andererseits als Trennzeichen zwischen anderen Verzeichnissen. Hierzu gleich mehr.

Die Grundinstallation gängiger Linux-Distributionen enthält normalerweise Zehntausende von Dateien in einer Verzeichnishierarchie, die größtenteils durch gewisse Konventionen vorstrukturiert ist. Über diese Verzeichnishierarchie erfahren Sie mehr in Kapitel 10.

6.1.3 Absolute und relative Pfadnamen

In einem Linux-System wird jede Datei durch einen Namen beschrieben. Dieser ergibt sich, indem man vom Wurzelverzeichnis ausgehend jedes Verzeichnis nennt, bis zu dem, in dem die Datei steht. Anschließend wird der Name der Datei selbst hinzugefügt. Ein Beispiel ist /home/hugo/brief.txt, das die Datei brief.txt bezeichnet, die sich im Verzeichnis hugo befindet, welches wiederum im Verzeichnis home zu finden ist. Das Verzeichnis home steht direkt im Wurzelverzeichnis. Solche Namen, die vom Wurzelverzeichnis ausgehen, heißen „absolute Pfadnamen” (engl. absolute path names). Wir sprechen von „Pfadnamen”, weil der Name einen „Pfad” durch den Verzeichnisbaum beschreibt, in dem die Namen von Verzeichnissen und Dateien vorkommen können (es handelt sich also um einen Sammelbegriff).

Jeder Prozess in einem Linux-System hat ein „aktuelles Verzeichnis“ (engl. current directory, auch working directory, „Arbeitsverzeichnis“). Dateinamen werden in diesem Verzeichnis gesucht. Somit ist brief.txt eine Abkürzung für „die Datei brief.txt im aktuellen Verzeichnis“ und susi/brief.txt steht für „die Datei brief.txt im Verzeichnis susi, das im aktuellen Verzeichnis steht“. Solche Namen, die vom aktuellen Verzeichnis ausgehen, nennen wir „relative Pfadnamen” (engl. relative path names).

💡 Sie können absolute von relativen Pfadnamen ganz einfach unterscheiden: Ein Pfadname, der mit „/” anfängt, ist absolut, alle anderen sind relativ.

💡 Das aktuelle Verzeichnis „vererbt“ sich vom Elternprozess an den Kindprozess. Wenn Sie also aus einer Shell heraus eine neue Shell (oder ein anderes Programm) starten, dann hat diese neue Shell dasselbe aktuelle Verzeichnis wie die Shell, aus der sie gestartet wurde. Sie können innerhalb der neuen Shell mit cd in ein anderes Verzeichnis wechseln. Das aktuelle Verzeichnis der alten Shell ändert sich dadurch jedoch nicht. Wenn Sie die neue Shell verlassen, befinden Sie sich wieder im (unveränderten) aktuellen Verzeichnis der alten Shell.

In relativen (oder auch absoluten) Pfadnamen gibt es zwei bequeme Abkürzungen: Der Name „..” steht für das dem jeweiligen Verzeichnis im Verzeichnisbaum übergeordnete Verzeichnis – im Falle von „/home/hugo” also beispielsweise „/home”. Das erlaubt es Ihnen, oftmals bequemer als über absolute Pfadnamen auf Dateien zuzugreifen, die sich aus der Sicht des aktuellen Verzeichnisses in einem „Seitenast“ des Verzeichnisbaums befinden. Nehmen wir an, /home/hugo enthält die Unterverzeichnisse briefe und romane. Mit briefe als aktuellem Verzeichnis könnten Sie sich über den relativen Pfadnamen „./romane/werther.txt” auf die Datei „werther.txt” im Verzeichnis romane beziehen, ohne den umständlichen absoluten Namen „/home/hugo/romane/werther.txt” angeben zu müssen.

Die zweite Abkürzung ist nicht ganz so offensichtlich: Der Name „.” in einem Verzeichnis steht immer für das Verzeichnis selbst. Es ist nicht unmittelbar klar, wozu man eine Methode braucht, um auf ein Verzeichnis zu verweisen, in dem man sich bereits befindet. Es gibt jedoch Situationen, in denen das sehr nützlich ist. Vielleicht wissen Sie es bereits (oder können es im Kapitel nachschlagen), aber die Shell sucht die Programmdateien für externe Kommandos in den Verzeichnissen, die in der Umgebungsvariablen PATH aufgelistet sind. Wenn Sie als Softwareentwickler ein Programm namens prog aufrufen wollen, das sich in einer Datei im aktuellen Verzeichnis befindet, das sich jedoch nicht in PATH befindet (aus Sicherheitsgründen immer eine gute Idee), dann können Sie mit:

$ /prog

Sie können die Shell trotzdem dazu bringen, Ihre Datei als Programm zu starten, ohne dass Sie einen absoluten Pfadnamen angeben müssen.

💡 Als Linux-Benutzer haben Sie ein „Heimatverzeichnis“, in dem Sie direkt nach dem Anmelden am System landen. Welches das ist, bestimmt der Systemadministrator beim Anlegen Ihres Benutzerkontos. Es heißt normalerweise so wie Ihr Benutzername und ist unterhalb von /home zu finden, beispielsweise /home/hugo für den Benutzer hugo.

6.2 Kommandos für Verzeichnisse

6.2.1 Das aktuelle Verzeichnis: cd & Co

In der Shell können Sie mit dem Befehl cd das aktuelle Verzeichnis wechseln.

Geben Sie dazu einfach das gewünschte Verzeichnis als Parameter an.

Tabelle 6.1: Einige Dateityp-Kennzeichnungen in ls

Dateityp Farbe Zeichen (ls -F) Kennung (ls -l)
gewöhnliche Datei schwarz keins -
ausführbare Datei grün * -
Verzeichnis blau / d
Link cyan @ l
$ cd briefe Wechseln ins Verzeichnis briefe
$ cd . Wechseln ins übergeordnete Verzeichnis

Wenn Sie keinen Parameter angeben, landen Sie in Ihrem Heimatverzeichnis:

$ cd
$ pwd
/home/hugo

Mit dem Kommando pwd (engl. print working directory) können Sie den absoluten Pfadnamen des aktuellen Verzeichnisses ausgeben, wie im Beispiel zu sehen.

Möglicherweise wird das aktuelle Verzeichnis auch in Ihrer Eingabeaufforderung angezeigt. Je nach Voreinstellung Ihres Systems könnte dort etwas wie folgt erscheinen:

hugo@red:~/briefe> _

Dabei ist "~/briefe" eine Abkürzung für "/home/hugo/briefe"; die Tilde ("~") steht für das Heimatverzeichnis des aktuellen Benutzers.

💡 Mit dem Kommando „cd -” wechseln Sie in das Verzeichnis, das vor dem letzten cd-Kommando aktuell war. Damit können Sie bequem zwischen zwei Verzeichnissen hin und her wechseln.

Übungen

✏️ 6.1 [2] Handelt es sich um ein externes Kommando oder ist es als internes Kommando in die Shell eingebaut? Warum?

✏️ 6.2 [3] Lesen Sie in der Handbuchseite der Bash nach, welche Funktionen die Kommandos pushd, popd und dirs haben. Überzeugen Sie sich, dass diese funktionieren.

6.2.2 Dateien und Verzeichnisse auflisten – ls

Zur Orientierung im Verzeichnisbaum ist es wichtig, die darin enthaltenen Dateien und Verzeichnisse ermitteln zu können. Hierzu dient das Kommando ls (list, „auflisten”).

Ohne Übergabe von Optionen werden diese Informationen als mehrspaltige, nach Dateinamen sortierte Tabelle ausgegeben. Da Farbbildschirme heutzutage keine Besonderheit mehr darstellen, hat es sich eingebürgert, Dateien verschiedener Typen in verschiedenen Farben darzustellen. (Über Dateitypen haben wir noch nicht gesprochen; dieses Thema wird im zehnten Kapitel behandelt.)

💡 Erfreulicherweise sind sich die meisten Distributionen über die Farben inzwischen weitgehend einig. Tabelle 6.1 nennt die verbreitetste Zuordnung.

Tabelle 6.2: Einige Optionen für ls

Option Wirkung
-a oder --all zeigt auch versteckte Dateien an
-i oder --inode gibt die eindeutige Dateinummer (Inode-Nr.) aus
-l oder --format=long liefert zusätzliche Informationen
--color=no verzichtet auf die Farbcodierung
-p oder -F markiert Dateityp durch angehängte Sonderzeichen
-r oder --reverse kehrt Sortierreihenfolge um
-R oder --recursive durchsucht auch Unterverzeichnisse (DOS: DIR/S)
-S oder --sort=size sortiert Dateien nach Größe (größte zuerst)
-t oder --sort=time sortiert Dateien nach Zeit (neueste zuerst)
-X oder --sort=extension sortiert Dateien nach Dateityp

💡 Auf Monochrom-Monitoren oder in Terminals ohne Farbunterstützung bietet es sich an, die Optionen -F oder -p anzugeben, um Dateitypen durch Sonderzeichen zu kennzeichnen. Hierbei werden zur Charakterisierung Sonderzeichen an die Dateinamen angehängt. Eine Auswahl der Zeichen finden Sie in Tabelle 6.1.

Mit dem Schalter -a (engl. all, „alle”) können Sie versteckte Dateien, deren Name mit einem Punkt beginnt, anzeigen. Sehr nützlich ist auch der Parameter -l (ein kleines „L“ für englisch long, „lang“). Damit werden nicht nur die Dateinamen, sondern auch diverse Zusatzinformationen ausgegeben. Zusatzinformationen

In manchen Linux-Distributionen sind für gängige Kombinationen dieser hilfreichen Optionen Abkürzungen voreingestellt. In den SUSE-Distributionen steht beispielsweise ein einfaches l für das Kommando ls -alF. Auch ll und la sind Abkürzungen für ls-Varianten.

Hier sehen Sie ls ohne und mit -l:

$ ls datei.txt datei2.dat
$ ls -l
-rw-r--r-1 hugo users 4711 Oct 4 11:11 datei.txt
-rw-r--r-1 hugo users 333 Oct 2 13:21 datei2.dat

Im ersten Fall werden alle sichtbaren Dateien des Verzeichnisses tabellarisch aufgelistet, im zweiten Fall werden die Zusatzinformationen hinzugefügt.

Die einzelnen Teile der langen Darstellung haben folgende Bedeutung: Die erste Spalte gibt den Dateityp (siehe Kapitel 10) an. Normale Dateien haben ein „-“, Verzeichnisse ein „d“ usw. (siehe „Kennbuchstabe“ in Tabelle 6.1). Die nächsten neun Zeichen informieren über die Zugriffsrechte. Danach folgen ein Referenzzähler, der Eigentümer der Datei (hier hugo) und die Gruppenzugehörigkeit der Datei (hier users). Nach der Dateigröße in Bytes sind das Datum und die Uhrzeit der letzten Änderung zu sehen. Abgeschlossen wird die Zeile durch den Dateinamen.

⚠️ Je nachdem, welche Sprache Sie eingestellt haben, können insbesondere die Datum- und Uhrzeitangaben ganz anders aussehen als in unserem Beispiel, das wir mit der Minimal-Sprachumgebung „C“ erzeugt haben. Das ist im interaktiven Gebrauch normalerweise kein Problem, kann aber zu Problemen führen, wenn Sie in einem Shellskript versuchen, die Ausgabe von „ls l” auseinanderzunehmen. (Ohne der Schulungsunterlage „Linux für Fortgeschrittene” vorgreifen zu wollen, empfehlen wir, in Shellskripten die Sprachumgebung auf einen definierten Wert zu setzen.)

💡 Wenn Sie die Zusatzinformationen für ein Verzeichnis (etwa /tmp) sehen wollen, hilft Ihnen „ls -l /tmp” nicht weiter, da ls dann die Daten für alle Dateien in /tmp auflistet. Mit der Option -d können Sie das unterdrücken und erhalten Informationen über /tmp selbst.

Neben den besprochenen Optionen erlaubt ls noch eine Vielzahl weiterer, von denen die wichtigsten in Tabelle 6.2 dargestellt sind.

In den LPI-Prüfungen „Linux Essentials” und „LPI-101” wird nicht erwartet, dass Sie alle Optionen von ls auswendig kennen. Die wichtigsten Optionen (z. B. -a, -l, -r, -R, -t) sollten Sie jedoch kennen

Übungen

✏️ 6.3 [1] Welche Dateien befinden sich im Verzeichnis /boot? Hat das Verzeichnis Unterverzeichnisse und wenn ja, welche?

✏️ 6.4 [2] Erklären Sie den Unterschied zwischen dem Befehl ls mit einem Dateinamen als Argument und dem Befehl ls mit einem Verzeichnisnamen als Argument.

✏️ 6.5 [2] Wie können Sie ls dazu bringen, bei einem Verzeichnisnamen als Argument Informationen über das benannte Verzeichnis selbst anstatt über die darin enthaltenen Dateien zu liefern?

6.2.3 Verzeichnisse anlegen und löschen: mkdir und rmdir

Um Ihre Dateien überschaubar zu halten, ist es sinnvoll, selbst Verzeichnisse anzulegen. In diesen „Ordnern” können Sie Ihre Dateien dann beispielsweise nach Themengebieten sortiert aufbewahren. Zur weiteren Strukturierung können Sie in diesen Ordnern auch Unterverzeichnisse anlegen. Ihrer Gliederung sind hier kaum Grenzen gesetzt.

Zum Anlegen neuer Verzeichnisse steht das Kommando mkdir (engl. make directory, „Verzeichnis erstellen”) zur Verfügung, das zwingend einen oder mehrere Verzeichnisnamen als Argument erwartet. Andernfalls erhalten Sie statt eines neuen Verzeichnisses lediglich eine Fehlermeldung. Um verschachtelte Verzeichnisse in einem Schritt neu anzulegen, können Sie die Option -p angeben. Andernfalls wird davon ausgegangen, dass alle Verzeichnisse bis auf das letzte im Namen schon existieren. Ein Beispiel:

$ mkdir bilder/urlaub
mkdir: cannot create directory `bilder/urlaub': No such file or directory
$ mkdir -p bilder/urlaub
$ cd bilder
$ ls -F
urlaub/

Es kann vorkommen, dass ein Verzeichnis nicht mehr benötigt wird. Zur besseren Übersicht können Sie es mit dem Kommando rmdir (engl. „remove directory“, „Verzeichnis entfernen“) wieder entfernen.

Wie bei dem Kommando mkdir müssen Sie auch hier den Namen mindestens eines zu löschenden Verzeichnisses angeben. Außerdem dürfen die Verzeichnisse keinerlei Einträge (Dateien oder Unterverzeichnisse) mehr enthalten. Auch hier wird nur das letzte Verzeichnis in jedem übergebenen Namen entfernt:

$ rmdir bilder/urlaub
$ ls -F
✁✁✁✁✁
bilder/
✁✁✁✁✁

Wenn Sie die Option -p angeben, können Sie alle leeren Unterverzeichnisse, die im Namen aufgeführt wurden, in einem Schritt von rechts her beseitigen.

$ mkdir -p bilder/urlaub/sommer
$ rmdir bilder/urlaub/sommer
$ ls -F bilder
bilder/urlaub/
$ rmdir -p bilder/urlaub
$ ls -F bilder
ls: bilder: No such file or directory

Übungen

✏️ 6.6 [!2] Erstellen Sie in Ihrem Heimatverzeichnis ein Verzeichnis namens „grd1-test” mit den Unterverzeichnissen dir1, dir2 und dir3. Wechseln Sie anschließend ins Verzeichnis „grd1-test/dir1” und legen Sie dort eine Datei namens hallo mit dem Inhalt hallo an (etwa mit einem Texteditor). Legen Sie anschließend im Verzeichnis grd1-test/dir2 eine Datei namens huhu mit dem Inhalt huhu an. Vergewissern Sie sich, dass diese Dateien angelegt wurden. Löschen Sie anschließend das Unterverzeichnis dir3 mit rmdir. Versuchen Sie anschließend, das Unterverzeichnis dir2 mit rmdir zu löschen. Was passiert und warum?

6.3 Suchmuster für Dateien

6.3.1 Einfache Suchmuster

Oft kommt es vor, dass Sie ein Kommando auf mehrere Dateien gleichzeitig ausführen möchten. Wenn Sie beispielsweise alle Dateien, deren Name mit p beginnt und mit „.c” endet, vom Verzeichnis prog1 ins Verzeichnis prog2 kopieren möchten, wäre es äußerst ärgerlich, wenn Sie jede Datei einzeln benennen müssten – zumindest, wenn es sich um mehr als zwei oder drei Dateien handelt! Viel bequemer ist es, die Suchmuster der Shell einzusetzen. Wenn Sie auf der Kommandozeile der Shell einen Parameter mit einem Stern angeben, zum Beispiel prog1/p*.c, ersetzt die Shell diesen Parameter im tatsächlichen Programmaufruf durch eine Liste aller Dateinamen, die zu dem Parameter passen.

„Passen” bedeutet in diesem Fall, dass im tatsächlichen Dateinamen statt des Sterns eine beliebig lange Folge von beliebigen Zeichen stehen darf. In Frage kommen zum Beispiel

prog1/p1.c prog1/paulchen.c prog1/pop-rock.c prog1/p.c

Beachten Sie vor allem den letzten Namen im Beispiel – „beliebig lang” bedeutet auch „Länge Null”. Das einzige Zeichen, auf das der Stern nicht passt, ist – na, fällt es Ihnen ein? – der Schrägstrich. Es ist normalerweise besser, ein Suchmuster wie den Stern auf das aktuelle Verzeichnis zu beschränken.

💡 Diese Suchmuster können Sie bequem mit echo testen. Ein

$ echo prog1/p*.c

gibt Ihnen unverbindlich und ohne weitere Konsequenzen jedweder Art die passenden Dateinamen aus.

💡 Wenn Sie wirklich ein Kommando auf alle Dateien im Verzeichnisbaum ab einem bestimmten Verzeichnis ausführen wollen: Auch dafür gibt es Mittel und Wege. Wir reden darüber in Abschnitt 6.4.4.

Das Suchmuster „” beschreibt „alle Dateien im aktuellen Verzeichnis” – mit Ausnahme der versteckten Dateien, deren Name mit einem Punkt beginnt. Um unangenehme Überraschungen auszuschließen, werden versteckte Dateien von Suchmustern nämlich konsequent ignoriert, es sei denn, Sie veranlassen explizit etwas wie „.*”, damit sie einbezogen werden.

💡 Sie kennen das Sternchen vielleicht von der Kommandozeile von Betriebssystemen wie DOS oder Windows. Dort sind Sie es gewohnt, ein Muster wie „.” anzugeben, um alle Dateien in einem Verzeichnis zu beschreiben.

Unter Linux ist das nicht korrekt, da das Muster „.” auf alle Dateien mit einem Punkt im Namen erfasst, da der Punkt nicht vorgeschrieben ist. Das Linux-Äquivalent ist, wie erwähnt, „*“.

Ein Fragezeichen steht als Suchmuster für genau ein beliebiges Zeichen (wieder ohne den Schrägstrich). Ein Muster wie „p?.c” passt also auf die Namen „p1.c”, „pa.c”, „p-.c” und „p..c” (unter anderem). Beachten Sie, dass es sich dabei um genau ein Zeichen handeln muss – die Option „gar nichts“ besteht hier nicht.

Merken Sie sich unbedingt folgenden wichtigen Umstand: Die Expansion von Suchmustern ist eine Leistung der Shell! Die aufgerufenen Kommandos wissen normalerweise nichts über Suchmuster und interessieren sich auch nicht dafür. Sie sehen lediglich Listen von Pfadnamen, ohne dass kommuniziert wird, ob diese direkt eingetippt wurden oder über Suchmuster entstanden sind.

💡 Übrigens sagt niemand, dass die Ergebnisse der Suchmuster immer als Pfadnamen interpretiert werden. Wenn Sie zum Beispiel in einem Verzeichnis eine Datei namens „-l” haben, dann liefert ein „ls *” in diesem Verzeichnis ein interessantes und vielleicht überraschendes Ergebnis (siehe Übung 6.9)1.

💡 Was passiert, wenn die Shell keine Datei findet, die auf das Suchmuster passt? In diesem Fall wird das Suchmuster direkt an das betreffende Kommando übergeben. Was es damit anfängt, ist seine eigene Sache. Typischerweise werden solche Suchmuster als Dateinamen interpretiert. Die betreffende „Datei” wird aber nicht gefunden und es erscheint eine Fehlermeldung. Es gibt aber auch Kommandos, die mit direkt übergebenen Suchmustern vernünftig umgehen können. Hier ist die Herausforderung dann eher, dafür zu sorgen, dass die Shell, die das Kommando aufruft, sich nicht mit ihrer eigenen Expansion vordrängelt. (Stichwort: Anführungszeichen.)

6.3.2 Zeichenklassen

Eine etwas genauere Einschränkung der passenden Zeichen in einem Suchmuster bieten „Zeichenklassen“: In einem Suchmuster der Form

prog[123].c

passen die eckigen Klammern auf genau die Zeichen, die darin aufgezählt werden (keine anderen). Das Muster im Beispiel passt also auf

prog1.c
prog2.c 
prog3.c

aber nicht

prog.c   Ein Zeichen muss es schon sein
prog4.c   Die 4 ist nicht in der Aufzählung 
proga.c   Das a auch nicht 
prog12.c` Genau ein Zeichen, bitte!

Als Schreibvereinfachung können Sie Bereiche angeben wie in

prog[1-9].c
[A-Z]brakadabra.txt

Die eckigen Klammern in der ersten Zeile passen zu allen Ziffern, die in der zweiten Zeile zu allen Großbuchstaben.

⚠️ Denken Sie daran, dass in den gängigen Zeichencode-Tabellen die Buchstaben nicht lückenlos hintereinander liegen: Ein Muster wie

prog[A-z].c

passt nicht nur auf progQ.c und progx.c, sondern zum Beispiel auch auf prog_.c. Schauen Sie dazu in einer ASCII-Tabelle nach, etwa mit dem Befehl „man ascii”. Wenn Sie nur „Groß- und Kleinbuchstaben” haben wollen, müssen Sie

prog[A-Za-z].c

schreiben.

💡 Selbst von einer Konstruktion wie

prog[A-Za-z].c

werden Umlaute nicht erfasst, obwohl die verdächtig aussehen wie Buchstaben.

passt nicht nur auf progQ.c und progx.c, sondern zum Beispiel auch auf prog_.c. Schauen Sie dazu in einer ASCII-Tabelle nach, etwa mit dem Befehl „man ascii”. Wenn Sie nur „Groß- und Kleinbuchstaben” haben wollen, müssen Sie

prog[!A-Za-z].c

passt auf alle Namen, bei denen das Zeichen zwischen g und „.” kein Buchstabe ist. Ausgenommen ist wie üblich der Schrägstrich.

6.3.3 Geschweifte Klammern

In einem Atemzug mit Shell-Suchmustern erwähnt, obwohl sie eigentlich nur eine entfernte Verwandte ist, wird die Expansion geschweifter Klammern in der Form „{rot,gelb,blau}.txt” – die Shell ersetzt dies durch „rot.txt, gelb.txt, blau.txt”.

Allgemein gilt: Ein Wort auf der Kommandozeile, das einige durch Kommas getrennte Textstücke innerhalb von geschweiften Klammern enthält, wird durch so viele Wörter ersetzt, wie Textstücke zwischen den Klammern stehen. Dabei wird in jedem dieser Wörter der komplette Klammerausdruck durch eines der Textstücke ersetzt. Dieser Ersetzungsvorgang findet ausschließlich auf textueller Basis statt und ist völlig unabhängig von der Existenz oder Nichtexistenz von Dateien oder Verzeichnissen. Im Gegensatz dazu produzieren Suchmuster immer nur solche Namen, die tatsächlich als Pfadnamen im System vorkommen.

Sie können auch mehrere Klammerausdrücke in einem Wort haben. In diesem Fall erhalten Sie als Ergebnis das kartesische Produkt, d. h. alle möglichen Kombinationen:

"{a,b,c}{1,2,3}.dat"

ergibt

a1.dat a2.dat a3.dat b1.dat b2.dat b3.dat c1.dat c2.dat c3.dat

Nützlich ist das zum Beispiel, um systematisch neue Verzeichnisse anzulegen; die normalen Suchmuster helfen da nicht, da sie ja nur bereits Existierendes finden können:

$ mkdir -p umsatz/200{8,9}/q{1,2,3,4}

Übungen

✏️ 6.7 [!1] Im aktuellen Verzeichnis stehen die Dateien

prog.c prog1.c prog2.c progabc.c prog p.txt p1.txt p21.txt p22.txt p22.dat

Auf welche dieser Dateinamen passen die Suchmuster

(a) prog.c,
(b) prog?.c,
(c) p?
.txt,
(d) p[12],
(e) p
,
(f) .?

✏️ 6.8 [!2] Was ist der Unterschied zwischen ls und „ls *”? (Tipp: Führen Sie beide Befehle in einem Verzeichnis mit Unterverzeichnissen aus.)

✏️ 6.9 [2] Erklären Sie, warum das folgende Kommando zur angezeigten Ausgabe führt:

$ ls
-l datei1 datei2 datei3
$ ls *
-rw-r--r-1 hugo users 0 Dec 19 11:24 datei1
-rw-r--r-1 hugo users 0 Dec 19 11:24 datei2
-rw-r--r-1 hugo users 0 Dec 19 11:24 datei3

✏️ 6.10 [2] Warum ist es sinnvoll, dass „*” nicht auf Dateinamen mit Punkt am Anfang passt?

Tabelle 6.3: Optionen für cp

Option Wirkung
-b (backup) Legt von existierenden Zieldateien Sicherungskopien an, indem an den Namen eine Tilde angehängt wird
-f (force) Überschreibt bereits existierende Zieldateien ohne Rückfrage
-i (interactive) fragt nach, ob bereits bestehende Dateien überschrieben werden sollen
-p (preserve) Behält möglichst alle Dateiattribute der Quelldatei bei
-R (recursive) Kopiert Verzeichnisse mit allen Unterverzeichnissen und allen darin enthaltenen Dateien
-u (update) Kopiert nur, wenn die Quelldatei neuer als die Zieldatei ist (oder noch keine Zieldatei existiert)
-v (verbose) Zeigt alle Aktivitäten auf dem Bildschirm

6.4 Umgang mit Dateien

6.4.1 Kopieren, Verschieben und Löschen – cp und Verwandte

Mit dem Kommando cp (engl. copy, „kopieren”) können Sie beliebige Dateien kopieren. Dabei gibt es zwei Vorgehensweisen:

  1. Wenn Sie cp die Namen von Quell- und Zieldatei als Argumente nennen, wird unter dem Zieldateinamen eine 1:1-Kopie des Inhalts der Quelldatei abgelegt. Standardmäßig fragt cp nicht nach, ob eine bereits existierende Zieldatei überschrieben werden soll, sondern tut dies einfach – hier ist also Vorsicht (oder die Option -i) angebracht.

  2. Sie können statt eines Zieldateinamens auch ein Zielverzeichnis angeben. Die Quelldatei wird dann unter ihrem alten Namen in das Verzeichnis hineinkopiert.

$ cp liste liste2
$ cp /etc/passwd
$ ls -l
-rw-r--r-- 1 hugo users 2500 Oct 4 11:11 liste
-rw-r--r-- 1 hugo users 2500 Oct 4 11:25 liste2
-rw-r--r-- 1 hugo users 8765 Oct 4 11:26 passwd

In unserem Beispiel haben wir zunächst mit dem Befehl cp eine exakte Kopie der Datei liste unter dem Namen liste2 erzeugt. Anschließend haben wir die Datei /etc/passwd ins aktuelle Verzeichnis kopiert, das durch einen Punkt repräsentiert wird. Die wichtigsten der zahlreichen cp-Optionen sind in Tabelle 6.3 aufgelistet.

Anstelle einer einzelnen Quelldatei ist auch eine Liste von Quelldateien oder die Verwendung von Shell-Suchmustern zulässig. Allerdings lassen sich auf diese Art nicht mehrere Dateien in einem Schritt kopieren und umbenennen, sondern nur in ein anderes Verzeichnis kopieren. Während in der DOS- und Windows-Welt mit COPY *.TXT *.BAK von jeder Datei mit der Endung TXT eine Sicherungskopie mit der Endung BAK angelegt wird, versagt unter Linux der Befehl cp *.txt *.bak normalerweise mit der Ausgabe einer Fehlermeldung.

💡 Um dies zu verstehen, müssen Sie sich vergegenwärtigen, wie die Shell diesen Befehl verarbeitet. Zunächst versucht sie, alle Suchmuster durch die passenden Dateinamen zu ersetzen, also beispielsweise *.txt durch brief1.txt und brief2.txt. Was mit *.bak passiert, hängt davon ab, auf wie viele Namen *.txt gepasst hat und ob es im aktuellen Verzeichnis Namen gibt, die auf *.bak passen. Allerdings wird fast nie das passieren, was ein DOS-Anwender erwarten würde. Normalerweise wird die Shell dem cp-Kommando das unersetzte Suchmuster *.bak als letztes einer Reihe von Argumenten übergeben. Aus Sicht von cp geht das schief, da es sich dabei nicht um einen gültigen Verzeichnisnamen handelt.

Während das Kommando cp eine exakte Kopie einer Datei anlegt, also die Datei physikalisch auf dem Datenträger verdoppelt oder auf einem anderen Datenträger identisch anlegt, ohne das Original zu verändern, dient der Befehl mv (engl. move, „bewegen”) dazu, eine Datei entweder an einen anderen Ort zu verschieben oder deren Namen zu verändern. Dieser Vorgang verändert lediglich Verzeichnisse, es sei denn, die Datei wird auf ein anderes Dateisystem verlagert, beispielsweise von einer Partition auf der Festplatte auf einen USB-Stick. Dabei wird tatsächlich ein physikalisches Verschieben (Kopieren an den neuen Ort und anschließendes Löschen am alten Ort) notwendig.

Die Syntax und Regeln von mv entsprechen denen von cp: Auch hier können Sie statt einer einzigen eine ganze Liste von Quelldateien angeben. Das Kommando erwartet daraufhin als letzte Angabe ein Zielverzeichnis. Der einzige Unterschied besteht darin, dass Sie neben gewöhnlichen Dateien auch Verzeichnisse umbenennen können.

Die Optionen -b, -f, -i, -u und -v haben bei mv die gleiche Funktion wie die bei cp beschriebenen Parameter.

$ mv passwd liste2
$ ls -l
-rw-r--r-1 hugo users 2500 Oct 4 11:11 liste
-rw-r--r-1 hugo users 8765 Oct 4 11:26 liste2

In diesem Beispiel wurde die ursprüngliche Datei liste2 durch die umbenannte Datei passwd ersetzt. Ebenso wie cp fragt auch mv nicht nach, wenn die angegebene Zieldatei bereits existiert, sondern überschreibt diese.

Der Befehl zum Löschen von Dateien lautet rm (engl. „remove“, „entfernen“). Um eine Datei löschen zu können, müssen Sie im entsprechenden Verzeichnis Schreibrechte besitzen. In Ihrem eigenen Heimatverzeichnis sind Sie der uneingeschränkte Herr im Haus und dürfen, gegebenenfalls nach einer entsprechenden Rückfrage, auch fremde Dateien löschen (sofern es welche gibt).

⚠️ Das Schreibrecht auf die Datei selbst ist zum Löschen dagegen völlig irrelevant, genauso wie die Frage, welchem Benutzer oder welcher Gruppe die Datei gehört.

rm geht bei seiner Arbeit genauso konsequent vor wie cp oder mv: Die angegebenen Dateien werden ohne Rückfrage oder Rückmeldung unwiederbringlich aus dem Dateisystem gelöscht. Besonders bei der Verwendung von Platzhaltern sollten Sie deshalb nur mit großer Vorsicht vorgehen. Im Unterschied zur DOS-Welt ist der Punkt innerhalb von Linux-Dateinamen ein Zeichen ohne besondere Bedeutung. Aus diesem Grund löscht das Kommando „rm *” unerbittlich alle nicht versteckten Dateien im aktuellen Verzeichnis. Dabei bleiben wenigstens die Unterverzeichnisse unbehelligt. Mit rm -r * müssen aber auch diese daran glauben.

💡 Als Systemadministrator können Sie mit unüberlegten Kommandos wie „rm -rf /” im Wurzelverzeichnis das gesamte System zerstören. Hier ist äußerste Aufmerksamkeit erforderlich! Leicht tippt man einmal „rm -rf bla” statt „rm -rf bla”.

Während rm ohne Rücksicht alle angegebenen Dateien löscht, geht rm -i etwas behutsamer vor.

$ rm -i lis*
rm: remove 'liste'? n
rm: remove 'liste2'? y
$ ls -l
-rw-r--r-1 hugo users 2500 Oct 4 11:11 liste

Wie das Beispiel zeigt, wird für jede zum Suchmuster passende Datei einzeln nachgefragt, ob sie gelöscht werden soll (mit y für engl. yes = ja oder n für engl. no = nein).

💡 In der deutschen Sprachumgebung können Sie auch j für ja verwenden.

y funktioniert trotzdem.

💡 Arbeitsumgebungen wie KDE unterstützen in der Regel die Verwendung eines Papierkorbs, in dem über den Dateimanager gelöschte Dateien zunächst landen. Aus dem Papierkorb können Sie sie bei Bedarf wiederherstellen. Es gibt auch für die Kommandozeile äquivalente Ansätze, wobei Sie auch dort auf eine Umdefinition von rm verzichten sollten. Neben den bereits beschriebenen Optionen -i und -r sind auch die bei cp beschriebenen Optionen -v und -f mit vergleichbarer Wirkung für rm zulässig.

Übungen

✏️ 6.11 [!2] Erstellen Sie im Heimatverzeichnis eine Kopie der Datei /etc/services und benennen Sie sie in myservices um. Benennen Sie diese dann in „srv.dat” um und kopieren Sie sie unter demselben Namen ins Verzeichnis „/tmp”. Löschen Sie anschließend beide Kopien der Datei.

✏️ 6.12 [1] Warum hat mv keine -R-Option wie cp?

✏️ 6.13 [!2] Angenommen, in einem Ihrer Verzeichnisse befindet sich eine Datei namens „-file” (mit einem Minuszeichen am Anfang des Namens). Wie würden Sie diese Datei entfernen?

✏️ 6.14 [2] Wenn Sie ein Verzeichnis haben, in dem Sie nicht versehentlich einem „rm *” zum Opfer fallen wollen, können Sie dort eine Datei namens „-i” anlegen.

bash $ > -i

Wenn Sie ein Verzeichnis haben, in dem Sie nicht versehentlich einem „rm *” zum Opfer fallen wollen, können Sie dort eine Datei namens „-i” anlegen.

6.4.2 Dateien verknüpfen – ln und ln -s

In Linux können Sie sogenannte Links anlegen, um einzelnen Dateien mehrere Namen zu geben. Doch wozu ist das gut? Die Anwendungsfälle reichen von Schreibvereinfachungen bei Datei- und Verzeichnisnamen über ein „Sicherheitsnetz” gegen ungewollte Löschoperationen bis zu Bequemlichkeiten beim Programmieren und Platzsparen bei großen Dateihierarchien, die in mehreren Versionen mit nur kleinen Änderungen vorliegen sollen.

Mit dem Befehl ln (engl. „link”, „verknüpfen”) können Sie einer Datei neben dem ursprünglichen Namen (erstes Argument) einen weiteren (zweites Argument) zuweisen:

$ ln liste liste2
$ ls -l
-rw-r--r-2 hugo users 2500 Oct 4 11:11 liste
-rw-r--r-2 hugo users 2500 Oct 4 11:11 liste2

Das Verzeichnis enthält nun scheinbar eine neue Datei namens liste2. Tatsächlich handelt es sich hierbei jedoch nur um zwei Verweise auf ein und dieselbe Datei. Einen Hinweis auf diesen Sachverhalt liefert der Referenzzähler, der in der zweiten Spalte der Ausgabe von „ls -l” zu sehen ist. Dessen Wert 2 gibt an, dass diese Datei zwei Namen hat. Ob es sich bei den beiden Dateinamen wirklich um Verweise auf dieselbe Datei handelt, lässt sich nur mithilfe von „ls -i” eindeutig entscheiden.

In diesem Fall muss die in der ersten Spalte angezeigte Dateinummer für beide Dateien identisch sein. Dateinummern, auch Inode-Nummern genannt, identifizieren Dateien eindeutig in ihrem Dateisystem:

$ ls -i
876543 liste 876543 liste2

💡 Der Begriff „Inode” steht für „Indirection Node” und bedeutet so viel wie „Indirektionsknoten” oder „Weiterleitungsknoten”. In den Inodes sind alle Informationen über eine Datei gespeichert, bis auf den Namen. Jede Datei hat genau einen Inode.

Wenn Sie den Inhalt einer der beiden Dateien verändern, ändert sich der Inhalt der anderen ebenfalls, da in Wirklichkeit nur eine einzige Datei mit der Nummer 876543 existiert. Wir haben der Datei mit der Nummer 876543 lediglich einen weiteren Namen gegeben.

💡 Verzeichnisse sind Tabellen, in denen Dateinamen Inode-Nummern zugeordnet werden. In einer Tabelle können offensichtlich mehrere Einträge mit verschiedenen Namen und derselben Inode-Nummer vorhanden sein. Ein Verzeichniseintrag mit einem Namen und einer Inode-Nummer wird als „Link” bezeichnet.

Sie sollten sich bewusst machen, dass es bei einer Datei mit zwei Links nicht möglich ist, festzustellen, welcher Name „das Original“ ist, also der erste Parameter im ln-Kommando. Aus der Sicht des Systems sind beide Namen absolut gleichwertig und ununterscheidbar.

⚠️ Verzeichnisse sind Tabellen, in denen Dateinamen Inode-Nummern zugeordnet sind. In einer Tabelle können mehrere Einträge mit verschiedenen Namen und derselben Inode-Nummer vorhanden sein. Ein Verzeichniseintrag mit einem Namen und einer Inode-Nummer wird als „Link” bezeichnet.

Sie sollten sich bewusst machen, dass es bei einer Datei mit zwei Links nicht möglich ist, festzustellen, welcher Name das „Original“ ist, also der erste Parameter im ln-Kommando. Aus Sicht des Systems sind beide Namen absolut gleichwertig und ununterscheidbar.

$ rm liste
$ ls -li
876543 -rw-r--r-1 hugo users 2500 Oct 4 11:11 liste2

💡 Da Inode-Nummern nur auf demselben physikalischen Dateisystem (Partition, USB-Stick usw.) eindeutig sind, sind solche Verknüpfungen nur in demselben Dateisystem möglich, in dem sich auch die Datei befindet.

💡 Ganz stimmt es allerdings nicht mit dem Löschen der Dateidaten: Wenn der letzte Dateiname entfernt wird, ist die Datei nicht mehr zugänglich. Wenn jedoch ein Prozess noch mit ihr arbeitet, darf er sie weiterbenutzen, bis er sie explizit schließt oder sich beendet. In Unix-Programmen ist das ein gängiges Verfahren für den Umgang mit temporären Dateien, die beim Programmende verschwinden sollen. Sie erzeugen sie mit Schreib- und Lesezugriff und „löschen” sie dann gleich wieder, ohne sie jedoch gleich zu schließen. Anschließend können Sie Daten hineinschreiben und später an den Dateianfang zurückspringen, um sie wieder zu lesen.

💡 Sie können ln außer mit zwei Argumenten auch mit einem oder vielen aufrufen. Im ersten Fall wird im aktuellen Verzeichnis ein Link mit demselben Namen wie die Ursprungsdatei angelegt (die sinnvollerweise nicht im aktuellen Verzeichnis liegen sollte). Im zweiten Fall werden alle benannten Dateien unter ihrem Namen in das durch das letzte Argument gegebene Verzeichnis „gelinkt” (denken Sie an mv).

Mit dem Kommando „cp -l” können Sie eine „Link-Farm” anlegen. Das heißt, die angegebenen Dateien werden nicht wie sonst üblich an den Zielort kopiert, sondern es werden Links auf die Originale angelegt.

$ mkdir prog-1.0.1 Neues Verzeichnis
$ cp -l prog-1.0/* prog-1.0.1

Der Vorteil dieses Ansatzes besteht darin, dass die Dateien nach wie vor nur einmal auf der Festplatte gespeichert sind und somit auch nur einmal Platz verbrauchen. Bei den heutigen Preisen für Speicherplatz ist das vielleicht nicht zwingend nötig, aber eine gängige Anwendung dieser Idee besteht darin, regelmäßige Sicherheitskopien großer Dateihierarchien anzulegen. Diese sollen dann als separate, datierte Dateibäume auf dem Archivmedium (Platte oder entfernter Rechner) erscheinen. Erfahrungsgemäß ändern sich die meisten Dateien nur selten. Wenn man diese Dateien nur einmal abspeichern muss statt immer wieder, addiert sich das mit der Zeit. Außerdem müssen die Dateien nicht immer wieder in die Sicherheitskopie geschrieben werden, was mitunter viel Zeit spart.

💡 Backup-Pakete, die diese Idee aufgreifen, sind beispielsweise Rsnapshot (http://www.rsnapshot.org/) oder Dirvish (http://www.dirvish.org/).

⚠️ Dieser Ansatz ist mit Vorsicht zu genießen: Zwar können identische Dateien über Links „dedupliziert” werden, Verzeichnisse jedoch nicht. Das bedeutet, dass für jeden datierten Verzeichnisbaum auf dem Archivmedium sämtliche Verzeichnisse neu angelegt werden müssen – selbst wenn sich in diesen wiederum nur Links auf existierende Dateien befinden. Dies kann zu sehr komplexen Verzeichnisstrukturen führen und im Extremfall dazu, dass eine Konsistenzprüfung des Archivmediums fehlschlägt, weil dem Rechner der Hauptspeicher ausgeht, um die Verzeichnishierarchie zu prüfen.

⚠️ Sie müssen natürlich auch aufpassen, wenn Sie etwa – wie im Beispiel angedeutet – eine „Kopie” eines Programmquellcodes als Link-Farm erstellen (was sich beispielsweise für den Linux-Quellcode plattenplatzmäßig durchaus rentieren könnte). Bevor Sie eine Datei in Ihrer neu angelegten Version ändern können, müssen Sie sicherstellen, dass es sich tatsächlich um eine eigenständige Datei handelt und nicht nur um einen Link auf das Original, das Sie höchstwahrscheinlich nicht ändern wollen. Das heißt, Sie müssen den Link zur Datei entweder manuell durch eine tatsächliche Kopie ersetzen oder einen Editor verwenden, der geänderte Versionen automatisch als eigenständige Datei speichert2.

Das ist noch nicht alles: In Linux-Systemen gibt es zwei Arten von Links. Das oben stehende Beispiel entspricht dem Standard des Kommandos ln und wird als Hardlink (engl. „feste Verknüpfung”) bezeichnet. Zur Identifikation der Datei wird dabei die Dateinummer gespeichert. Symbolische Links (in Anlehnung an die eben genannten „Hard Links” auch „Soft Links” oder „weiche Verknüpfungen”) sind selbst eigentlich Dateien, in denen aber nur der Name der „Zieldatei” des Links steht. Gleichzeitig wird vermerkt, dass es sich um einen symbolischen Link handelt und dass bei Zugriffen auf den Link in Wirklichkeit die Zieldatei gemeint ist. Im Gegensatz zu harten Links „weiß” die Zieldatei nicht, dass ein symbolischer Link auf sie existiert. Das Anlegen oder Löschen eines symbolischen Links hat keine Auswirkungen auf die Zieldatei. Wird die Zieldatei dagegen entfernt, weist der symbolische Link ins Leere (Zugriffe führen zu einer Fehlermeldung).

Im Gegensatz zu harten Links erlauben symbolische Links Verweise auf Verzeichnisse sowie auf Dateien, die sich im Verzeichnisbaum auf anderen physikalischen Dateisystemen befinden. In der Praxis werden symbolische Links oft bevorzugt, da sich die Verknüpfungen anhand des Pfadnamens leichter nachvollziehen lassen.

💡 Symbolische Links werden gerne verwendet, wenn sich die Namen von Dateien oder Verzeichnissen ändern, aber eine gewisse Rückwärtskompatibilität gewünscht ist. Beispielsweise wurde vereinbart, die Postfächer von Systembenutzern (in denen ihre ungelesenen E-Mails gespeichert sind) im Verzeichnis /var/mail abzulegen. Traditionell hieß das Verzeichnis jedoch /var/spool/mail und viele Programme haben diesen Namen fest einprogrammiert. Um die Umstellung auf /var/mail zu erleichtern, kann eine Distribution also einen symbolischen Link mit dem Namen /var/spool/mail einrichten, der auf /var/mail verweist. (Mit harten Links wäre das nicht möglich, da harte Links auf Verzeichnisse nicht erlaubt sind.)

Um einen symbolischen Link zu erzeugen, müssen Sie dem Kommando ln die Option -s übergeben:

$ ln -s /var/log kurz
$ ls -l
-rw-r--r-1 hugo users 2500 Oct 4 11:11 liste2
lrwxrwxrwx 1 hugo users 14 Oct 4 11:40 kurz -> /var/log
$ cd kurz
$ pwd -P
/var/log

Neben der Option -s zur Erstellung von „Soft Links” unterstützt das Kommando ln unter anderem die bereits bei cp besprochenen Optionen -b, -f, -i und -v.

Um nicht mehr benötigte symbolische Links zu entfernen, können Sie diese einfach wie gewöhnliche Dateien mit dem Kommando rm löschen. Dabei wirkt die Operation auf den Link und nicht auf das Ziel des Links:

$ cd
$ rm kurz
$ ls
liste2

Wie Sie weiter oben gesehen haben, zeigt „ls -l” für symbolische Links auch die Datei an, auf die der Link zeigt. Mit den Optionen -L und -H können Sie ls dazu bringen, symbolische Links direkt aufzulösen:

$ mkdir dir
$ echo XXXXXXXXXX >dir/datei
$ ln -s datei dir/symlink
$ ls -l dir
insgesamt 4
-rw-r--r-1 hugo users 11 Jan 21 12:29 datei
lrwxrwxrwx 1 hugo users 5 Jan 21 12:29 symlink -> datei
$ ls -lL dir
-rw-r--r-1 hugo users 11 Jan 21 12:29 datei
-rw-r--r-1 hugo users 11 Jan 21 12:29 symlink
$ ls -lH dir
-rw-r--r-1 hugo users 11 Jan 21 12:29 datei
lrwxrwxrwx 1 hugo users 5 Jan 21 12:29 symlink -> datei
$ ls -l dir/symlink
lrwxrwxrwx 1 hugo users 5 Jan 21 12:29 dir/symlink -> datei
$ ls -lH dir/symlink
-rw-r--r-1 hugo users 11 Jan 21 12:29 dir/symlink

Der Unterschied zwischen den Optionen -L und -H besteht darin, dass die Option -L symbolische Links immer auflöst und die Informationen über die eigentliche Datei anzeigt (der angezeigte Name ist trotzdem immer der des Links). Die Option -H löst dagegen nur die direkt auf der Kommandozeile angegebenen Links auf, wie die letzten drei Kommandos im Beispiel illustrieren.

In Analogie zu „cp -l” erstellt „cp -s” Link-Farmen auf Basis von symbolischen Links. Diese sind allerdings nicht ganz so nützlich wie die oben gezeigten mit harten Links. „cp -a” kopiert Dateihierarchien so, wie sie sind, und behält dabei symbolische Links bei. „cp -L” sorgt beim Kopieren dafür, dass symbolische Links durch die Dateien ersetzt werden, auf die sie zeigen. „cp -P” schließt dies aus.

Übungen

✏️ 6.15 [!2] Erzeugen Sie eine Datei mit beliebigem Inhalt in Ihrem Heimatverzeichnis, beispielsweise mit dem Befehl „echo Hallo >~/hallo” oder mithilfe eines Texteditors. Legen Sie unter dem Namen „link” einen harten Link auf die Datei an. Überzeugen Sie sich, dass nun zwei Namen für die Datei existieren. Versuchen Sie, den Inhalt der Datei mit einem Editor zu ändern. Was passiert?

✏️ 6.16 [!2] Legen Sie unter dem Namen ~/symlink einen symbolischen Link zur Datei aus der vorherigen Aufgabe an. Prüfen Sie anschließend, ob der Zugriff funktioniert. Was passiert, wenn Sie die Zieldatei des Links löschen?

✏️ 6.17 [!2] Auf welches Verzeichnis zeigt der Link „./“ im Verzeichnis „/“?

✏️ 6.18 [3] Betrachten Sie das folgende Kommando und dessen Ausgabe:

$ ls -ai /
2 330211 etc 1 proc 4303 var
2 . 2 home 65153 root
4833 bin 244322 lib 313777 sbin
228033 boot 460935 mnt 244321 tmp
330625 dev 460940 opt 390938 usr

Offensichtlich haben die Verzeichnisse / und /home dieselbe Inodenummer.

Da es sich dabei offensichtlich nicht wirklich um dasselbe Verzeichnis handeln kann – können Sie dieses Phänomen erklären?

✏️ 6.19 [2] Betrachten Sie die Inode-Nummern der Links „.» und „..” im Wurzelverzeichnis (/) sowie in einigen anderen Verzeichnissen Ihrer Wahl. Was fällt Ihnen auf?

✏️ 6.20 [3] Wir haben gesagt, dass harte Links auf Verzeichnisse nicht erlaubt sind. Können Sie uns einen Grund dafür nennen?

✏️ 6.21 [3] Wie erkennt man in der Ausgabe von „ls -l ~“ ein Unterverzeichnis von ~ ohne weitere Unterverzeichnisse?

✏️ 6.22 [2] Wie verhalten sich die Befehle „ls -lH” und „ls -lL”, wenn ein symbolischer Link auf einen anderen symbolischen Link zeigt?

Tabelle 6.4: Tastaturbefehle für more

Taste Wirkung
zeigt nächste Zeile an zeigt nächste Seite an
b zeigt vorherige Seite an
h gibt einen Hilfstext aus
q beendet more
/ ⟨Wort⟩ ↩ sucht nach ⟨Wort⟩
! ⟨Kommando⟩ ↩ führt ⟨Kommando⟩ in Sub-Shell aus
v ruft Editor (vi) auf
Strg + l zeichnet Bildschirm neu

✏️ 6.23 [3] Wie lang darf eine „Kette” von symbolischen Links maximal sein? Mit anderen Worten: Wenn Sie mit einem symbolischen Link auf eine Datei beginnen, wie oft können Sie einen symbolischen Link anlegen, der auf den jeweils vorherigen symbolischen Link verweist?

✏️ 6.24 [4] (Nachdenk- und Rechercheaufgabe:) Was benötigt mehr Platz auf der Festplatte, ein harter oder ein symbolischer Link? Warum?

6.4.3 Dateiinhalte anzeigen – more und less

Mit dem Befehl more (engl. für „mehr“) können Textdateien komfortabel am Bildschirm dargestellt werden. Mit diesem Kommando können Sie längere Texte seitenweise betrachten. Die Anzeige wird dabei nach einer Bildschirmseite automatisch angehalten und in der letzten Zeile erscheint »--More--«, gegebenenfalls ergänzt durch eine Prozentangabe. Der Prozentwert zeigt an, welcher Anteil der Datei bereits dargestellt wurde. Durch Drücken einer Taste wird die Ausgabe des restlichen Textes fortgesetzt. Welche Tasten welche Funktion besitzen, zeigt Tabelle 6.4.

more erlaubt natürlich auch einige Optionen. Mit der Option -s (engl. squeeze, „quetschen”) werden mehrere aufeinanderfolgende Leerzeilen zu einer einzigen zusammengefasst. Seitenvorschübe (repräsentiert durch das Symbol „^L”) werden bei Übergabe der Option -l ignoriert. Mit der Option -n ⟨Zahl⟩ kann die Zeilenzahl des Bildschirms auf ⟨Zahl⟩ Zeilen eingestellt werden. Andernfalls liest More den aktuellen Wert aus der Variablen TERM aus.

Die Textdarstellung von More ist nach wie vor gravierenden Einschränkungen unterworfen. So fehlt beispielsweise eine allgemein mögliche Rückwärtsbewegung in der Ausgabe. Aus diesem Grund wird heute meist die verbesserte Version Less (engl. für „weniger”3) eingesetzt. Nun können Sie sich mit den Cursortasten wie gewohnt vertikal durch den Text bewegen. Ferner wurden die Suchroutinen erweitert, sodass eine Suche sowohl Textauf- als auch -abwärts möglich ist. Tabelle 6.5 bietet einen Überblick über die wichtigsten Tastaturbefehle.

Wie in Kapitel 5 bereits erwähnt, ist less üblicherweise als Anzeigeprogramm für man voreingestellt. Alle diese Tastaturkommandos greifen daher auch bei der Anzeige der Online-Hilfe über man.

6.4.4 Dateien suchen – find

Welcher Anwender kennt das nicht: „Da gab es doch mal eine Datei, aber wo war die gleich?“ Natürlich können Sie alle Verzeichnisse mühsam von Hand nach der gesuchten Datei durchsuchen. Aber Linux wäre nicht Linux, wenn es Ihnen nicht hilfreich zur Seite stehen würde.

Mit dem Befehl find können Sie den Verzeichnisbaum rekursiv nach Dateien durchsuchen, die den angegebenen Kriterien entsprechen. „Rekursiv” bedeutet in diesem Fall, dass auch alle im Startverzeichnis enthaltenen Unterverzeichnisse, deren Unterverzeichnisse usw. mit erfasst werden. Als Suchergebnis liefert find die Pfadnamen der gefundenen Dateien, die dann an andere Programme weitergeleitet werden können. Zur Verdeutlichung der Befehlsstruktur hier ein Beispiel:

$ find -user hugo -print
./liste

Tabelle 6.5: Tastaturbefehle für less

Taste Wirkung
↓ oder e oder j oder ↩ zeigt nächste Zeile an
f oder zeigt nächste Seite an
↑ oder y oder k zeigt vorherige Zeile an
b zeigt vorherige Seite an
Pos1 oder g an den Textanfang springen
Ende oder ⇑ + g ans Textende springen
p ⟨Zahl⟩ ↩ springt an Position ⟨Zahl⟩ (in %) des Textes
h gibt einen Hilfetext aus
q beendet less
/ ⟨Wort⟩ ↩ sucht abwärts nach ⟨Wort⟩
n setzt Suche abwärts fort
? ⟨Wort⟩ ↩ sucht aufwärts nach ⟨Wort⟩
⇑ + n setzt Suche aufwärts fort
! ⟨Kommando⟩ ↩ führt ⟨Kommando⟩ in Sub-Shell aus
v ruft Editor (vi) auf
r oder Strg + l zeichnet Bildschirm neu

Hier wird das aktuelle Verzeichnis inklusive aller Unterverzeichnisse nach Dateien durchsucht, die dem Benutzer hugo gehören. Die Option -print gibt das Suchergebnis, im Beispiel nur eine einzige Datei, auf dem Bildschirm aus. Zur Arbeitserleichterung wird die Angabe „-print” daher automatisch ergänzt, wenn Sie nicht ausdrücklich angeben, wie mit den gefundenen Dateinamen zu verfahren ist.

Wie das Beispiel zeigt, benötigt find einige Angaben, um seine Aufgabe ordnungsgemäß zu erledigen.

Die Auswahl des Startverzeichnisses sollte mit Bedacht erfolgen. Wenn Sie das Wurzelverzeichnis wählen, wird die gesuchte Datei – sofern sie existiert – mit Sicherheit gefunden, der Suchvorgang kann jedoch viel Zeit in Anspruch nehmen. Natürlich dürfen Sie nur in denjenigen Verzeichnissen suchen, auf die Sie angemessene Zugriffsrechte haben.

💡 Wenn Sie einen absoluten Pfadnamen für das Startverzeichnis angeben, werden als Suchergebnis absolute Pfadnamen geliefert. Wenn Sie hingegen ein relativ angegebenes Startverzeichnis angeben, werden entsprechend relative Resultate geliefert.

Anstelle eines einzelnen Startverzeichnisses können Sie auch eine Liste von Verzeichnisnamen angeben, die dann der Reihe nach durchsucht werden.

Mit diesen Auswahlkriterien können Sie die Merkmale der zu findenden Dateien genauer festlegen. Tabelle 6.6 enthält eine Auswahl zulässiger Angaben, weitere stehen in der Dokumentation.

Tabelle 6.6: Testkriterien von find

Test Wirkung
-name Sucht nach passenden Dateinamen. Hierbei sind alle Sonderzeichen nutzbar, die von der Shell zur Verfügung gestellt werden. Mit -iname werden dabei Groß und Kleinbuchstaben gleich behandelt.
-user Sucht nach Dateien, die dem angegebenen Benutzer gehören. Dabei ist statt des Anwendernamens auch die Angabe der eindeutigen Benutzernummer, der UID, möglich.
-group Sucht nach Dateien, die zu der angegebenen Gruppe gehören. Wie bei -user ist hier statt des Gruppennamens auch die Angabe der eindeutigen Gruppennummer, der GID, zulässig.
-type Ermöglicht die Suche nach verschiedenen Dateitypen (siehe Abschnitt 10.2). Dabei werden unterschieden:
  • b blockorientierte Gerätedatei
  • c zeichenorientierte Gerätedatei
  • d Verzeichnis
  • f normale Datei
  • l Symbolisches Link
  • p FIFO (named pipe)
  • s Unix-Domain-Socket
-size Sucht nach Dateien bestimmter Größe. Zahlenwerte werden dabei als 512-Byte-Blöcke interpretiert, durch ein nachgestelltes c sind Größenangaben in Byte, durch k in Kibibyte erlaubt. Vorangestellte Plus oder Minuszeichen entsprechen Unter undObergrenzen, womit ein Größenbereich abgedeckt werden kann. Das Kriterium -size +10k trifft z. B. für alle Dateien zu, die größer als 10 KiB sind.
-atime (engl. access, »Zugriff«) sucht Dateien nach dem Zeitpunkt des letzten Zugriffs. Hier sowie für die beiden nächsten Auswahlkriterien wird der Zeitraum in Tagen angegeben; …min statt …time ermöglicht eine minutengenaue Suche.
-mtime (engl. modification, »Veränderung«) wählt passende Dateien über den Zeitpunkt der letzten Veränderung aus.
-ctime (engl. change, »Änderung«) sucht Dateien anhand der letzten Änderung der Inodes (durch Zugriff auf den Inhalt, Rechteänderung, Umbenennen etc.)
-perm Findet nur Dateien, deren Zugriffsrechte genau mit den angegebenen übereinstimmen. Die Festlegung erfolgt mittels einer Oktalzahl, die beim Befehl chmod beschrieben wird. Möchte man nur nach einem bestimmten Recht suchen, muss der Oktalzahl ein Minuszeichen vorangestellt werden, z. B. berücksichtigt -perm -20 alle Dateien, die Gruppenschreibrechte besitzen, unabhängig von deren übrigen Zugriffsrechten.
-links Sucht nach Dateien, deren Referenzzähler den angegebenen Zahlenwert hat.
inum Findet Verweise auf die Datei mit der angegebenen InodeNummer.

Wenn Sie mehrere Auswahlkriterien gleichzeitig angeben, werden diese automatisch mit Und verknüpft, d. h., alle müssen erfüllt werden. Daneben unterstützt find noch weitere logische Operationen (siehe Tabelle 6.7).

Kompliziertere logische Verknüpfungen von Auswahlkriterien sollten in runde Klammern eingeschlossen werden, um fehlerhafte Auswertungen zu vermeiden. Die Klammern müssen Sie natürlich vor der Shell verstecken:

$ find \( -type d -o -name ""A*"" \) -print
./.
./..
./bilder
./Abfall
$ _

Das Beispiel listet alle Dateien auf dem Bildschirm auf, die entweder Verzeichnisse repräsentieren oder deren Name mit einem A beginnt, oder beide Kriterien erfüllen.

Die Ausgabe der Suchergebnisse auf dem Bildschirm erfolgt, wie eingangs erwähnt, mit der Kommandooption -print. Daneben gibt es mit -exec (engl. execute, „ausführen”) und -ok noch zwei weitere Optionen, die Folgekommandos mit den gefundenen Dateien ausführen. Dabei unterscheidet sich -ok nur dadurch von -exec, dass vor der Ausführung des Folgekommandos die Zustimmung des Benutzers eingeholt wird, wohingegen -exec diese stillschweigend voraussetzt. Im weiteren Text steht daher -exec stellvertretend für beide Varianten.

Zur Anwendung von -exec gibt es einige allgemeingültige Regeln:

  • Das Kommando hinter -exec muss mit einem Strichpunkt (';') abgeschlossen werden. Da dieser in üblichen Shells eine Sonderbedeutung hat, muss er maskiert werden (etwa als „\;” oder mit Anführungszeichen), damit find ihn überhaupt erkennt.

  • Zwei geschweifte Klammern (»{}«) werden im Kommando durch den gefundenen Dateinamen ersetzt. Am besten setzen Sie die geschweiften Klammern in Anführungszeichen, um Probleme mit Leerzeichen in Dateinamen zu vermeiden.

Zum Beispiel:

$ find -user hugo -exec ls -l '{}' \;
-rw-r--r-1 hugo users 4711 Oct 4 11:11 datei.txt
$ _

Das obenstehende Beispiel sucht nach allen Dateien im aktuellen Verzeichnis, die dem Benutzer hugo gehören, und führt für diese das Kommando „ls -l” aus. Mehr Sinn ergibt folgende Variante:

$ find -atime +13 -exec rm -i '{}' \;

Hiermit werden alle Dateien im aktuellen Verzeichnis und darunter interaktiv gelöscht, auf die seit zwei Wochen oder länger nicht mehr zugegriffen wurde.

💡 Mitunter – etwa im letzten Beispiel – ist es sehr ineffizient, für jeden einzelnen Dateinamen extra einen neuen Prozess mit dem -exec-Kommando zu starten. In diesem Fall hilft oft das Kommando xargs, das so viele Dateinamen wie möglich sammelt, bevor es damit tatsächlich ein Kommando ausführt:

Tabelle 6.7: Logische Operatoren für find

Zeichen Operator Bedeutung
! Nicht die folgende Bedingung darf nicht zutreffen
-a and (Und) die Bedingungen links und rechts vom -a müssen zutreffen
-o or (Oder) von den Bedingungen links und rechts vom -o muss mindestens eine zutreffen
$ find -atime +13 | xargs -r rm -i

xargs liest seine Standardeingabe bis zu einem bestimmten, konfigurierbaren Maximum an Zeichen oder Zeilen und verwendet das Gelesene als Argumente für das angegebene Kommando (in diesem Fall rm). Dabei gelten Leerzeichen als Trennzeichen für die Argumente (sie können mit Anführungszeichen oder „\” maskiert werden) oder Zeilentrenner. Das Kommando wird nur so oft aufgerufen, wie es zur Verarbeitung der Eingabe nötig ist. Die Option r von xargs sorgt dafür, dass das Kommando rm nur ausgeführt wird, wenn find tatsächlich einen Dateinamen übergibt – ansonsten würde es zumindest einmal gestartet.

💡 Die Kombination aus find und xargs kommt bei eigenartigen Dateinamen in Schwierigkeiten, etwa solchen, die Leerzeichen oder gar Zeilentrenner enthalten. Diese werden dann als Trennzeichen fehlinterpretiert. Die todsichere Abhilfe dagegen besteht darin, die find-Option „-print0” zu benutzen, die wie „-print” die Namen der gefundenen Dateien ausgibt, diese aber nicht durch Zeilentrenner, sondern durch Nullbytes voneinander trennt. Da das Nullbyte in Dateinamen nicht auftauchen kann, ist keine Verwechslung mehr möglich. xargs muss mit der Option „-0” aufgerufen werden, um diese Form der Eingabe zu verstehen.

$ find -atime +13 -print0 | xargs -0r rm -i

Übungen

✏️ 6.25 [!2] Finden Sie alle Dateien in Ihrem System, die größer als 1 MiB sind, und geben Sie deren Namen aus.

✏️ 6.26 [2] Wie können Sie find verwenden, um eine Datei mit einem merkwürdigen Namen (etwa mit unsichtbaren Kontrollzeichen oder Umlauten, die von älteren Shells nicht unterstützt werden) zu löschen?

✏️ 6.27 [3] (Beim zweiten Durcharbeiten.) Wie würden Sie beim Abmelden dafür sorgen, dass Dateien, die Ihnen gehören und sich in /tmp befinden, automatisch gelöscht werden?

6.4.5 Dateien schnell finden – locate und slocate

Mit dem Kommando find können Dateien gemäß einer Vielzahl von Kriterien gesucht werden. Dabei muss jedoch die komplette Dateihierarchie unterhalb des Startverzeichnisses durchlaufen werden. Je nach dessen Umfang kann es also durchaus eine Weile dauern, bis die Suche abgeschlossen ist. Für den typischen Anwendungsfall, die Suche nach Dateien mit einem bestimmten Namen, gibt es ein beschleunigtes Verfahren.

Das Kommando locate gibt alle Dateien aus, deren Name einem bestimmten Shell-Suchmuster entspricht. Im einfachsten Fall ist das eine simple Zeichenkette.

$ locate brief.txt
/home/hugo/Briefe/brief.txt
/home/hugo/Briefe/omabrief.txt
/home/hugo/Briefe/omabrief.txt~
✁✁✁✁✁

⚠️ Obwohl locate ein ziemlich grundlegender Dienst ist (was unter anderem daran erkennbar ist, dass das Programm zum LPIC-1-Stoff gehört), gehört er nicht bei allen Linux-Systemen zur Standardinstallation.

Wenn Sie beispielsweise eine SUSE-Distribution verwenden, müssen Sie das Paket „findutils-locate” explizit nachinstallieren, bevor Sie locate benutzen können.

Die Sonderzeichen „”, „?” und „[…]” funktionieren bei locate wie bei Suchmustern in der Shell. Während eine Anfrage ohne Suchmuster-Sonderzeichen alle Namen liefert, in denen der Suchbegriff irgendwo auftaucht, gibt eine Anfrage mit Suchmuster-Sonderzeichen nur diejenigen Namen aus, die vom Suchbegriff vollständig beschrieben werden. Aus diesem Grund beginnen Suchmuster-Anfragen mit locate meistens mit „“:

$ locate ""*/brief.t*""
/home/hugo/Briefe/brief.txt
/home/hugo/Briefe/brief.tab
✁✁✁✁✁

💡 Am besten stellen Sie locate-Anfragen mit Sonderzeichen in Anführungszeichen, damit die Shell diese nicht auszuwerten versucht.

Der Schrägstrich (»/«) wird nicht als Sonderzeichen behandelt:

$ locate Briefe/oma
/home/hugo/Briefe/omabrief.txt
/home/hugo/Briefe/omabrief.txt~

locate ist so schnell, weil es nicht das gesamte Dateisystem absucht, sondern in einer „Datenbank” von Dateinamen nachschaut. Diese Datenbank wurde irgendwann vorher mit dem Programm updatedb angelegt. Das bedeutet natürlich auch, dass Dateien, die seit der letzten Aktualisierung der Datenbank hinzugefügt wurden, nicht gefunden werden. Umgekehrt können auch die Namen von Dateien geliefert werden, die seitdem gelöscht wurden.

💡 Mit der Option „-e” können Sie locate dazu bringen, nur tatsächlich existierende Dateinamen zu liefern. Die Datenbank wird standardmäßig täglich per Cron oder Systemd-Timer aktualisiert. Die Konfiguration erfolgt über /etc/updatedb.conf oder /etc/sysconfig/locate.

Das Programm updatedb baut die Datenbank für locate auf. Da dieser Vorgang einige Zeit dauern kann, sorgt Ihr Systemverwalter in der Regel dafür, dass dies geschieht, wenn das System sonst nicht viel zu tun hat, beispielsweise nachts auf ständig eingeschalteten Serversystemen.

💡 Der dafür nötige Systemdienst cron wird in der Publikation „Linux für Fortgeschrittene” ausführlich besprochen. Für den Moment mag es genügen zu wissen, dass die meisten Linux-Distributionen einen Mechanismus mitliefern, der dafür sorgt, dass updatedb regelmäßig aufgerufen wird.

Als Systemverwalter können Sie konfigurieren, welche Verzeichnisse updatedb beim Erstellen der Datenbank berücksichtigt. Wie das im Detail passiert, ist distributionsabhängig: updatedb selbst liest keine Konfigurationsdatei, sondern übernimmt seine Konfigurationseinstellungen über Kommandozeilenargumente oder teilweise Umgebungsvariablen. Die meisten Distributionen rufen jedoch updatedb über ein Shellskript auf, das zuvor eine Datei wie /etc/updatedb.conf oder /etc/sysconfig/locate einliest. In dieser Datei können beispielsweise geeignete Umgebungsvariablen gesetzt werden.

💡 Dieses Shellskript finden Sie beispielsweise in /etc/cron.daily (Details sind distributionsabhängig).

Mit UPDATEDB können Sie zum Beispiel angeben, welche Verzeichnisse durchsucht werden sollen und welche ausgenommen werden sollen. Das Programm erlaubt auch die Definition von "Netz-Dateisystemen". Das sind Systeme, die von verschiedenen Rechnern verwendet werden und in deren Wurzelverzeichnissen Datenbanken geführt werden sollen. So muss nicht jeder Rechner dafür seine eigene Datenbank aufbauen.

💡 Eine wichtige Konfigurationseinstellung ist die des Benutzers, mit dessen Identität die Aktualisierung von update_db ausgeführt wird. Dafür gibt es im Wesentlichen zwei Möglichkeiten:

  1. updatedb läuft mit den Rechten von root und kann so jede Datei in die Datenbank aufnehmen. Das hat jedoch zur Folge, dass Benutzer Dateinamen in Verzeichnissen ausspähen können, für die sie gar keine Zugriffsrechte haben, beispielsweise die Heimatverzeichnisse anderer Benutzer.

  2. updatedb läuft mit eingeschränkten Rechten, etwa denen des Benutzers nobody. In diesem Fall landen nur diejenigen Dateinamen in der Datenbank, die in Verzeichnissen stehen, deren Inhalt nobody auflisten darf.

💡 Das Programm mlocate (oder slocate auf älteren Systemen) umgeht dieses Problem, indem es neben dem Namen einer Datei auch deren Eigentümer, Gruppenzugehörigkeit und Zugriffsrechte in der Datenbank speichert. mlocate gibt einen Dateinamen nur dann aus, wenn der Benutzer tatsächlich Zugriff auf die betreffende Datei hat. Auch slocate verfügt über ein „updatedb“-Programm, das allerdings nur ein anderer Name für slocate selbst ist.

In vielen Fällen ist slocate so installiert, dass es auch unter dem Namen locate aufgerufen werden kann.

Übungen

✏️ 6.28 [!1] Der Dateiname README ist sehr populär. Bitte geben Sie die absoluten Pfadnamen aller Dateien auf Ihrem System an, die den Namen README tragen.

✏️ 6.29 [2] Legen Sie eine neue Datei in Ihrem Heimatverzeichnis an und überzeugen Sie sich mithilfe eines locate-Aufrufs davon, dass diese Datei nicht gefunden wird (wählen Sie dazu einen hinreichend ausgefallenen Dateinamen). Rufen Sie dann (mit Administratorrechten) das Programm updatedb auf. Wird Ihre neue Datei danach mit dem Befehl locate gefunden? Löschen Sie die Datei wieder und wiederholen Sie die vorherigen Schritte.

✏️ 6.30 [1] Überzeugen Sie sich von der Funktionsweise von slocate, indem Sie als gewöhnlicher Benutzer nach Dateien wie /etc/shadow suchen.

6.5 Kommandos in diesem Kapitel

Kommando Beschreibung manpage
cd Wechselt das aktuelle Arbeitsverzeichnis der Shell bash(1)
convmv Konvertiert Dateinamen zwischen Zeichenkodierungen convmv(1)
cp Kopiert Dateien cp(1)
find Sucht nach Dateien, die bestimmte Kriterien erfüllen find(1), Info: find
less Zeigt Texte (etwa Handbuchseiten) seitenweise an less(1)
ln Stellt (”harte“ oder symbolische) Links her ln(1)
locate Sucht Dateien über ihren Namen in einer Dateinamensdatenbank locate(1)
ls Listet Dateien oder den Inhalt von Verzeichnissen auf ls(1)
mkdir Legt neue Verzeichnisse an mkdir(1)
more Zeigt Textdaten seitenweise an more(1)
mv Verschiebt Dateien in andere Verzeichnisse oder benennt sie um mv(1)
pwd Gibt den Namen des aktuellen Arbeitsverzeichnisses aus pwd(1), bash(1)
rm Löscht Dateien oder Verzeichnisse rm(1)
rmdir Entfernt (leere) Verzeichnisse rmdir(1)
slocate Sucht Dateien über ihren Namen in einer Datenbank und beachtet dabei deren Zugriffsrechte slocate(1)
updatedb Erstellt die Dateinamensdatenbank für locate updatedb(1)
xargs Konstruiert Kommandozeilen aus seiner Standardeingabe "xargs(1), Info: find

6.6 Zusammenfassung

  • In Dateinamen dürfen fast alle Zeichen verwendet werden. Im Interesse der Portabilität sollte man sich jedoch auf Buchstaben, Ziffern und einige Sonderzeichen beschränken.

  • Linux unterscheidet bei Dateinamen zwischen Groß- und Kleinschreibung.

  • Absolute Pfade beginnen immer mit einem Schrägstrich und benennen alle Verzeichnisse vom Wurzelverzeichnis des Verzeichnisbaums bis zum betreffenden Verzeichnis bzw. der Datei. Relative Pfade beziehen sich auf das „aktuelle Verzeichnis”.

  • Mit dem Befehl cd können Sie das aktuelle Verzeichnis der Shell ändern und mit dem Befehl pwd können Sie dessen Namen anzeigen.

  • ls gibt Informationen über Dateien und Verzeichnisse aus.

  • Mit den Befehlen mkdir und rmdir können Sie Verzeichnisse anlegen bzw. entfernen.

  • Die Kommandos cp, mv und rm kopieren, verschieben bzw. löschen Dateien und Verzeichnisse.

  • Mit ln können Sie „harte” und „symbolische” Links anlegen.

  • more und less dienen zum seitenweisen Anzeigen von Dateien auf dem Terminal.

  • find sucht nach Dateien oder Verzeichnissen, die bestimmte Kriterien erfüllen.


  1. Für CP/M sind Sie wahrscheinlich zu jung. 

  2. Wenn Sie den Vim (alias vi) verwenden, können Sie in die Datei vimrc in Ihrem Heimatverzeichnis das Kommando »set backupcopy=auto,breakhardlink« schreiben. 

  3. Ein schwaches Wortspiel – denken Sie an »weniger ist mehr«.