Datei in-place ändern

Moien,

ich hab hier Dateien (50 - 200 GB pro Datei, binäres Format) mit einem kleinen Schönheitsfehler: in den ersten 2 KB steht der ASCII-String: „AS32D“. Das ist falsch und müsste „AS23D“ sein. Ich könnte natürlich die ganze Datei durch sed pumpen, nur dauert das bei einigen dutzende Dateien (insgesamt grob 10 TB) recht lange. Ein Programm zum direkten ändern gibt es nicht (ist kein gängiges Format und die Firma ist pleite…).

Kann man da nicht was mit perl oder sed oder tr basteln? Ich brauche kein fertiges Programm, nur ein Hinweis auf die richtige Stelle im Handbuch.

Danke

Hallo pumkin,

wie wäre es mit

perl -pi -e ‚s/pattern/replacement/g‘ file1

mfg tf

Moien

-i ist auch nur pseudo in-place. Real macht -i ein rename, liest die alte Datei, schreibt gleichzeitig eine neue und löscht dann die alte.

Das macht bei 10TB keinen Spass, vorallem weil in dem Fall auch noch gleichzeitig auf einer Platte gelesen und geschreiben wird. Dann lieber sed und von einer Platte auf eine andere.

cu

Hallo pumpkin,

-i ist auch nur pseudo in-place. Real macht -i ein rename,
liest die alte Datei, schreibt gleichzeitig eine neue und
löscht dann die alte.

Ich denke, der gute alte Editor ed, denn Du ja auch skript-gesteuert benutzen kannst, ist der einzige, der echt in-place ersetzt. Wenn ich folgendes ed-skript

1,$ s/AS32D/AS23D/
w
q

auf Dateien loslasse

ed \* 
wird der Inhalt verändert, aber die Inode-Nr bleibt gleich, das heisst ja wohl, es gibt kein löschen und neu schreiben, sondern nur echtes in-place ersetzen, oder sehe ich das falsch?

Viele Grüße
Marvin

Moien

Ich denke, der gute alte Editor ed, denn Du ja auch
skript-gesteuert benutzen kannst, ist der einzige, der echt
in-place ersetzt.

Ich kann es gerade nicht testen, aber die Zeile:

„If invoked with a file argument, then a copy of file is read into the editor’s buffer. Changes are made to this copy and not directly to file itself.“

aus der man-page läst böses ahnen. Ein kurzer Test mit einer kleinen 2 GB Datei war auch nicht sonderlich erbaulich.

wird der Inhalt verändert, aber die Inode-Nr bleibt gleich,
das heisst ja wohl, es gibt kein löschen und neu schreiben,
sondern nur echtes in-place ersetzen, oder sehe ich das
falsch?

Der macht wahrscheinlich ein truncate und schreibt dann das neue Zeug rein. Dabei bleiben die inodes meistens auch erhalten.

Ich glaube das läuft auf eine sed-Orgie über Nacht raus.

cu

Hallo pumpkin,

Ein kurzer Test mit einer
kleinen 2 GB Datei war auch nicht sonderlich erbaulich.

Na schade, der Versuch war’s wert…

Ich glaube das läuft auf eine sed-Orgie über Nacht raus.

Und wie wäre es mit einem kleinen C oder C++ Programm? Ist ja sicher schnell geschrieben und läuft wahrscheinlich auch schneller als sed, vermute ich jetzt mal ganz kühn.

Viele Grüße
Marvin

Tach!

ich hab hier Dateien (50 - 200 GB pro Datei, binäres Format)
mit einem kleinen Schönheitsfehler: in den ersten 2 KB steht
der ASCII-String: „AS32D“. Das ist falsch und müsste „AS23D“
sein. Ich könnte natürlich die ganze Datei durch sed pumpen,
nur dauert das bei einigen dutzende Dateien (insgesamt grob 10
TB) recht lange. Ein Programm zum direkten ändern gibt es
nicht (ist kein gängiges Format und die Firma ist pleite…).

Falls du sicher bist, daß der String nur in den ersten 2kb vorkommt, könntest du wirklich mit perl arbeiten, z.B. so (nur Ausschnitt, bitte selber testen):

# variablen deklarieren etc...

sysopen(IKFILE, $inputfname, O\_RDWR)
 or die "Fehler: kann Datei nicht im R/W-Mode oeffnen ($!)";

my $indata;
my $rlen = read IKFILE, $indata, 2048; # ersetn 2K Bytes lesen
if ($rlen != 2048)
{
 print STDERR "Fehler: kann die ersten 2048 Bytes nicht lesen\n";
 exit 1;
}


seek(IKFILE, 0, 0) # rewind to file position 0
 or die "Seeking: $!";
$indata =~ s/AS32D/AS23D/; # Ersetzung durchfuehren (global??? -\> /g)
print IKFILE $new\_asatz;
close IKFILE;
exit 0;

HTH
bernhard

Moien

Falls du sicher bist, daß der String nur in den ersten 2kb
vorkommt, könntest du wirklich mit perl arbeiten, z.B. so (nur
Ausschnitt, bitte selber testen):

Darauf ist es hinaus gelaufen: Kumpel hat in Bash was mit dd und sed gebaut. Lief über Nacht und war heute morgen fertig. An sich kopiert er den Header raus (dd count=10 if= …) , ändert ihn mit sed (sed -i s/…) und setzt die Daten dann wieder zusammen (was wildes mit dd skip und seek).

… die Dateien scheinen entgegen aller Erwartungen OK zu sein …

Danke für das Skript.

cu