Aufzucht und Hege von Shell-Scripts: Dateien bearbeiten

Lesen aus und Schreiben in Dateien

Hier geht es um ein alltägliches Problem: Ich will eine Datei verändern, der veränderte Inhalt soll also wieder in der gleichen Datei landen. Man liest dann ab und zu Ratschläge wie: tr -d '\r' <datei >datei. Tut das nicht! Das könnte der Datei weh tun, sprich, sie verstümmeln oder komplett leeren. Solche Konstruktionen sind ein Lotto-Spiel mit ebenso geringen Gewinnchancen wie in den staatlichen Lotterien. Ihr wisst nicht, in welcher Reihenfolge das ausgeführte Programm (oder die Shell) Dateidescriptoren öffnet und schließt, wie gelesen und geschrieben wird (also welche "Portionen" einer Datei in einem Rutsch rein- oder rausgehen), wie der darunterliegende Dateisystem-Treiber zwischenspeichert, ob das System gerade flusht, also Cache-Inhalte auf die Platte nagelt, ... Ihr wisst eigentlich gar nichts ;-) Also lasst die Finger von solchen "Lösungen".

Es gibt einige Programme, die das "In Place"-Editieren von Dateien erlauben, z. B. sed -i. Außerdem kann man wahrscheinlich in einigen Programmen solches "In Place"-Editieren mit ruhigem Gewissen unter Beachtung bestimmter Regeln durchführen - wenn Ihr z. B. in einem awk-Script die Datei erst in Programmvariablen / Arrays einlest und dann im END-Abschnitt rausschreibt (dann ist das Einlesen beendet), dann sollte das eigentlich gutgehen. Aber für diesen Tipp übernehme ich keinerlei Gewähr!

Die meiner Meinung nach beste Lösung ist das Zwischenspeichern in temporären Dateien, und zwar am sichersten so:

  # temporaere Datei mit einem eindeutigen Namen erzeugen, bei einem Fehler abbrechen
  TMP_FILE=`mktemp` || exit 1
  # dafuer sorgen, dass die temp. Datei bei einem Abbruch verschwindet
  trap "rm -f $TMP_FILE 2>/dev/null; exit 1" 1 2 3 15 ERR
  # Jetzt die Ausgabe in die temp. Datei, bei Erfolg in Originaldatei verschieben
  tr -d '\r' </Pfad/zu/meiner/Datei >$TMP_FILE && mv $TMP_FILE /Pfad/zu/meiner/Datei

Zum trap steht im folgenden Abschnitt was, und wo noch viel mehr? Jepp, im Bash-Manual.