find: Dateien manipulieren und ersetzen

sheep

sheep

Aktives Mitglied
Thread Starter
Dabei seit
21.03.2005
Beiträge
1.255
Reaktionspunkte
25
Hallo allerseits

Ich möchte gerne mit find bestimmte Dateien (sehr viele) in einem Verzeichnis finden und von diesen jeweils die ersten paar (konkret: 43) Text-Zeilen abschneiden. Das Resultat (also die jeweilige Datei ohne die ersten 43 Zeilen) soll die ursprüngliche Datei ersetzen.

Klingt einfach, aber ich beiss' mir die Zähne aus :(.

So sieht das bis jetzt aus:
find . -name *_*.html -print -exec tail -n+43 {} \;

Was jetzt passiert ist natürlich, dass das Resultat einfach auf der Konsole ausgegeben wird, es soll aber die jeweiligen Dateien ersetzen.

Ich hoffe, ich drücke mich klar aus - das muss doch zu schaffen sein... Es geht übrigens darum, eine grosse Menge HTML-Dateien etwas umzuformatieren, wenn ich das Prinzip mal habe, glaube ich eigentlich, dass das hiermit recht einfach funktionieren würde.
 
du musst natürlich den tail output redirecten mit >
aber frag mich jetzt nicht, ob der dann nicht direkt die datei so überschreibt das du da einen loop hast ;)
 
oneOeight schrieb:
du musst natürlich den tail output redirecten mit >
aber frag mich jetzt nicht, ob der dann nicht direkt die datei so überschreibt das du da einen loop hast ;)
Darauf bin ich auch schon gekommen, das Problem ist, dass ich nicht weiss, was ich als Input angeben muss - ./ gibt Fehlermeldung, * ebenfalls.

Gehen muss das ja irgendwie, das ist doch bestimmt keine sooo exotische Aufgabenstellung :).
 
mit input meinst du auf was redirectet werden soll?
du musst natürlich den filenamen nehmen, den dir find ausspuckt.
frag mich jetzt nicht, wie man das jetzt macht, guck in die find man page ;)
 
oneOeight schrieb:
mit input meinst du auf was redirectet werden soll?
du musst natürlich den filenamen nehmen, den dir find ausspuckt.
frag mich jetzt nicht, wie man das jetzt macht, guck in die find man page ;)
Ja eben, genau das finde ich nicht. Aus der man werde ich der Hinsicht überhaupt nicht schlau, eigentlich ist {} der Dateiname, aber das haut nicht hin (so wie es bis jetzt ist, schon, aber nicht als Ziel des Redirects).
 
Ohne dein Problem jetzt lösen zu können... was spricht gegen ein schönes kleines Bash-Script?

z.B.

Code:
for x in `find . -name *_*.html -print`; do sed -e '1,43d' $x > $x; done

Ich muss zugeben, ich hab es nicht getestet. Prinzipiell müsste es aber funktionieren. :teeth:
 
autoexec.bat schrieb:
Ohne dein Problem jetzt lösen zu können... was spricht gegen ein schönes kleines Bash-Script?

z.B.

Code:
for x in `find . -name *_*.html -print`; do sed -e '1,43d' $x > $x; done

Ich muss zugeben, ich hab es nicht getestet. Prinzipiell müsste es aber funktionieren. :teeth:
Dieser Ansatz tut immerhin schon etwas. Das Problem ist, dass die Dateien dadurch gänzlich "ausgeleert" werden, sie sind alle noch da, aber gähnend leer.

Hast du irgendeine Idee, wie das zustandekommt? Die Idee mit der Schleife ist wirklich hilfreich (ich verstehe die Funktionsweise von find nicht wirklich, daher hätte ich das nicht hinbekommen), vielen Dank schon mal dafür.
 
Hmm... merkwürdig. Scheint wohl irgendein Problem mit dem umleiten der Ausgaben zu sein. Sehe jetzt spontan nicht wirklich was das Problem ist.

Was allerdings funktionieren müsste ist:

Code:
sed -i -e '1,43d'
Da du damit schonmal das umleiten der Ausgabe gespart hast kannst du dir auch die for-Schleife sparen und das wieder in deinen find Befehl einbauen. Also

Code:
 find . -name *_*.html -print -exec sed -i -e '1,43d' {} \;
Also mir gefällts. :hehehe:
 
@ autoexec.bat

:hug:
einfach göttlich, perfekt, wunderbar :).

Vielen herzlichen Dank, das war echt eine grosse Hilfe!
 
Noch kurz ein Wort zum Thema Ausgabeumleitung.
Die Funktionsweise der Shell ist wie folgt.

Es wird beim Analysieren der Befehlszeile erkannt, dass eine Ausgabeumleitung stattfindet (ohne append).
Also wird zuerst eine leere Datei mit dem angegebenen Namen angelegt - und dabei die bereits vorhandene ersetzt.

Anschließened wird diese leere Datei mit dem "sed"-Befehl bearbeitet.
Das Ergebnis ist eine leere Datei.

Mit der Z-Shell kann man sich übrigens den find-Befehl komplett schenken:
Code:
sed -i -e '1,43d' **/*_*.html
 
zur vollständigekit: ein >> löscht das file nicht, sondern hängt ran...
 
Vielen Dank euch beiden noch für die Erläuterungen.

Das erklärt, warum die Dateien leer waren. Nun funktioniert es ja wunderbar und ich bin voll happy :D
 
sheep schrieb:
Nun funktioniert es ja wunderbar und ich bin voll happy :D

Nachdem maceis bereits das "Warum" erklärt hat, hier noch ein Beispiel, wie es mit Ausgabeumleitung und find ohne externes Shell-Script gehen kann. Der Vorteil dieser Lösung ist auch der, daß die Sache mit (leider vorkommenden) Spaces in Dateinamen funktioniert:

Code:
find . -name "*_*.html" -print0 | xargs -0 -n 1 sh -c 'tail -n+43 "$1" > "$1".new && mv "$1".new "$1"' "$0"
 
Zurück
Oben Unten