Das Symptom
Gesucht ist das Erstellungsdatum einer Datei, etwa um zu klären, seit wann ein Bericht auf dem Server liegt. ls -lc liefert eine Zeit, stat hat eine Zeile namens Change, und das c klingt so verlässlich nach created, dass niemand weiter nachdenkt. Ergebnis: Die Datei wurde angeblich gestern angelegt. Tatsächlich liegt sie seit Monaten dort, und gestern hat nur ein Backup- oder Verteilungsprogramm ihre Rechte oder ihren Eigentümer neu gesetzt.
Auf einem deutsch eingestellten System wird es nicht besser. GNU stat übersetzt seine Zeilen; in der hier geprüften Fassung 9.7 heißt die Zeile für ctime Geändert und die für mtime Modifiziert, was zusammen eher nach Synonymen klingt als nach zwei verschiedenen Dingen. Am teuersten wird die Verwechslung in Skripten: Ein Aufräumjob, der alte Dateien mit find -ctime aussortiert, verschont alles, dessen Rechte kürzlich jemand angefasst hat.
Die „Layer 8“-Wahrheit
Linux führt für jede Datei mehrere Zeitstempel, und keiner von ihnen heißt creation, nur weil er mit c anfängt. inode(7) definiert ctime so: „This is the file’s last status change timestamp. It is changed by writing or by setting inode information (i.e., owner, group, link count, mode, etc.).“ Ein chmod, ein chown, ein neuer harter Link: Jede dieser Kleinigkeiten setzt ctime auf jetzt, ohne dass sich am Inhalt ein Byte geändert hat. Die mtime bleibt in diesen Fällen stehen, und auch das steht ausdrücklich dort: „The mtime timestamp is not changed for changes in owner, group, hard link count, or mode.“
Das echte Anlegedatum ist ein eigenes Feld, btime. inode(7) beschreibt es knapp: „The file’s creation timestamp. This is set on file creation and not changed subsequently.“ Es steckt nicht in der klassischen stat-Struktur, sondern nur in statx, und die Handbuchseite hängt eine Warnung an: „The btime timestamp was not historically present on UNIX systems and is not currently supported by most Linux filesystems.“ Ob das eigene Dateisystem dazugehört, zeigt stat selbst: %w gibt laut stat(1) einen Strich aus, wenn die Zeit unbekannt ist.
Der Layer-8-Fehler ist also ein Lesefehler mit Folgen. ls(1) sagt bei der Option -c klar, was angezeigt wird, nämlich die ctime als „time of last change of file status information“. stat beschriftet die Zeile mit Change, nicht mit Created. Und find unterscheidet zwischen geänderten Daten und geändertem Status. Wer das Alter des Inhalts meint, nimmt mtime. Wer das Anlegen meint, nimmt btime, falls es sie gibt. ctime ist für keine dieser Fragen die richtige Antwort, sondern beantwortet eine dritte: Wann hat zuletzt jemand an den Verwaltungsdaten dieser Datei gedreht?