Warum behandeln `cp` und` rm` Verzeichnisse getrennt?

10

Warum mögen cpund rmbehandeln Tools Verzeichnisse getrennt von regulären Dateien? In beiden Fällen muss der Benutzer explizit angeben, dass er ein rekursives Verhalten wünscht, da er sich sonst überhaupt nicht mit Verzeichnissen befasst.

Meine erste Interaktion (vor einiger Zeit) mit Computern fand in einer Windows / GUI / Point-and-Click / Drag & Drop-Umgebung statt. Es schien immer natürlich, dass sich diese Vorgänge unabhängig vom Ziel gleich verhalten.

Dieses Verhalten frustriert mich besonders, wenn ich Befehle mit Platzhaltern gebe. Was ist, wenn ich alles in einem Verzeichnis ( *) entfernen möchte, außer nicht leere Unterverzeichnisse ?

Ich kann mir nur vorstellen, dass dies eine Art Sicherheitsmerkmal ist, das den Benutzer daran hindert, sich in den Fuß zu schießen, aber dies widerspricht meinem Verständnis einiger Unix-Prinzipien:

  • Unix schützt den Benutzer normalerweise nicht vor sich selbst. Es wurde immer davon ausgegangen, dass der Benutzer weiß, was er tut.
  • Für Unix ist alles eine Datei. Ist ein Verzeichnis nicht nur eine andere Datei? Warum werden sie unterschiedlich behandelt?

Meine Fragen:

  • Ist dieses Verhalten auf eine technische Einschränkung zurückzuführen oder handelt es sich um eine bewusste Entscheidung?

Und im letzteren Fall,

  • Gibt es historische Berichte über die Gründe, die diese Wahl motiviert haben?
Rahmu
quelle
Für rmzumindest, wenn man es den Unterschied zwischen Dateien und Verzeichnisse ignorieren möchten, können Sie in Ihrem setzen ~/.bashrcDatei: alias rm='rm -r'.
BenjiWiebe
1
Siehe auch die andere, aber verwandte Frage unix.stackexchange.com/questions/46066/…
derobert
1
Sie können cp und rm nicht mit dem Windows-Dateimanager vergleichen. Starten Sie cmd.exe und versuchen Sie, das Verhalten zu kopieren und zu löschen und zu vergleichen.
ott--

Antworten:

11

Deroberts Warum benötigt das Unix- MV- Programm keine -R-Option (rekursiv) für Verzeichnisse, aber cp benötigt sie? Grundsätzlich wird Ihre Frage beantwortet: Das Kopieren oder Entfernen einer regulären Datei unterscheidet sich von der gleichen Operation mit einem Verzeichnis, da Sie für ein Verzeichnis alle darin enthaltenen Dateien verarbeiten müssen. Daher ist die Operation grundlegend anders.

Erwähnenswert ist auch, dass es ein spezielles Dienstprogramm gibt, rmdirdas nur auf leere Verzeichnisse angewendet werden kann. Ohne die Fakten zu überprüfen, führt dies zu dem Schluss, dass ursprünglich möglicherweise rmnur Nicht-Verzeichnisse entfernt werden konnten und ein tiefes Entfernen durch rekursives Verwenden rmvon leeren Verzeichnissen und anschließendes rmdirEntfernen dieser Verzeichnisse erreicht werden musste .

Peterph
quelle
rmdirist auch der Name des Systemaufrufs, mit dem ein Verzeichnis gelöscht wurde. Das Verzeichnis muss für den Systemaufruf leer sein, und das gleichnamige Dienstprogramm ist nur "Front-End", ähnlich dem unlinkBefehl und dem Dienstprogramm.
Jordanm
Genau - das lässt mich glauben, dass rmVerzeichnisse ursprünglich möglicherweise überhaupt nicht entfernt werden konnten (da die Befehlszeilen-Dienstprogramme oft nur relativ einfache Wrapper um Syscalls sind).
Peterph
Der Titel meiner Frage könnte irreführend sein, wenn ich nach den technischen Details frage. Ich habe gefragt, ob es eine bewusste Entscheidung ist. Ich frage mich, ob ich der einzige bin, der der Meinung ist, dass dieses Verhalten aus Sicht des Endbenutzers inkonsistent ist. Ich akzeptiere Ihre Antwort, weil sie indirekt meine Frage beantwortet: Technische Einschränkungen in Unix-Interna (auf Syscall-Ebene) scheinen der Ursprung dieses Verhaltens zu sein, und das Erbe hindert uns wahrscheinlich daran, es heute anders zu machen. Sollen uns "einfache Wrapper um Syscalls" nicht intelligentere Verhaltensweisen geben?
Rahm
2
Vom Endbenutzer-POV scheint es in der Tat seltsam, aber Sie haben tatsächlich nach den Gründen gefragt. :) Was die Wrapper betrifft - alles hängt davon ab, wie "einfach" sie sind (und was Sie immer noch "einfach" nennen möchten). Modern ist rmdefinitiv nicht nur ein einfacher Wrapper (es kann auch Mroe-Dateien und Verzeichnisse auf einmal entfernen). Wenn Sie ihm die -rOption nicht geben möchten, verwenden Sie die Aliasing-Funktionalität Ihrer Shell oder erstellen Sie einen eigenen Wrapper, der sie anbringt (was langsamer wäre, aber unabhängig von der verwendeten Shell).
Peterph
2

In einigen UNIX-Varianten gibt die Manpage von rm den Befehl zum Aufheben der Verknüpfung einer Datei an.
Unter UNIX sind Dateien Objekte im Dateisystem namens Inodes, ohne Namen oder Speicherort außer einer ID im Dateisystem. Ihre Namen sind Verweise auf sie in verschiedenen Verzeichnissen. Hierbei handelt es sich um einen Dateityp, der die darin aufgeführten Dateien (oder Verzeichnisse, da es sich um Dateien handelt) indiziert.
Wenn Sie die Verknüpfung einer Datei aufheben, verringert sich die Referenzanzahl der Datei, und wenn sie 0 erreicht, wird sie tatsächlich gelöscht, da sie vom Dateisystem als frei markiert wird und ihre Blöcke / Speicherbereiche ebenfalls als frei markiert werden.

Wenn Sie die Möglichkeit hatten, ein Verzeichnis zu erstellen, ohne zuvor die Verknüpfung der darin enthaltenen Dateien aufzuheben, erreichen Sie einen Punkt, an dem Sie Inodes in Ihrem Dateisystem referenziert haben, auf die jedoch auf keine normale Weise zugegriffen werden kann.
Da sie entsprechend ihrer Referenzanzahl referenziert werden, werden sie nicht als gelöscht markiert und gehen verloren.
Dies wird noch komplexer, wenn die verlorenen "Dateien" Verzeichnisse sind, und erhöht somit die potenzielle Menge an verlorenem Speicher im Dateisystem.

Daher wurde rm -r hinzugefügt, um das Leben von UNIX-Benutzern auf Kosten des Standard-UNIX-Geistes zu vereinfachen, da es komplexer ist als die klassischen UNIX-Dienstprogramme, da es in Verzeichnisse absteigt und Dateien darin entfernt.

Darüber hinaus hatten Systeme in der frühen Zeit von UNIX nicht viel Speicher, und die Zuordnung der rekursiven Struktur eines Verzeichnisses hatte einen Leistungsverlust zur Folge, und manchmal war es unmöglich, auf die Aufteilung der Arbeit zu verzichten.

cp, liest eine Datei und kopiert sie Block für Block. Wenn ein Verzeichnis genauso kopiert würde wie eine Datei, würde es Verweise auf die darin enthaltenen Dateien hinzufügen, ohne deren Referenzanzahl zu erhöhen, was zu inkonsistenten Daten führen könnte (wenn in einen Inode gelesen / geschrieben wird, dessen Blöcke seit ihrer Freigabe als frei markiert sind Original-Inode wurde gelöscht), verlorene Daten - da das Löschen des letzten (bekannten) Verweises auf eine Datei dazu führen kann, dass die Inode-Nummer wiederverwendet wird.

Für die tl; dr-Crowd:
Verzeichnisse in UNIX sind zwar eine Art von Datei, aber da die darin enthaltenen Informationen vom System unterschiedlich behandelt werden, da es sich um Metadaten des Dateisystems handelt, können die Befehle, die Dateien bearbeiten, nicht in Verzeichnissen ohne a funktionieren Änderung ihres Verhaltens, um auch die abhängigen Metadaten zu manipulieren.

Didi Kohen
quelle