Hi! Wie gehe ich am besten vor, wenn ich bei bestimmten Dateien im Filesystem was verändern möchte? zB. das body TAG aller HTML und PHP Seiten. Suche nach <body> und ersetze durch <body color="#aabbcc"> Vermute mal, das wirde ne tolle Mischung aus find, pipes und greps. Aber da bin ich noch nicht sooo firm drin. Vorallem das "replace" macht mir noch Schwierigkeiten. Wodurch wird das gesteuert? Würde mich über hilfreiche Tips freuen! Viele Grüße Tol
Hallo! Am Dienstag, 10. Februar 2004 16:38 schrieb Tol:
Hi!
Wie gehe ich am besten vor, wenn ich bei bestimmten Dateien im Filesystem was verändern möchte? zB. das body TAG aller HTML und PHP Seiten. Suche nach <body> und ersetze durch <body color="#aabbcc">
Schau Dir mal awk an. Oder Perl. Beide sind für genau solche Zwecke gedacht.
Vermute mal, das wirde ne tolle Mischung aus find, pipes und greps.
Kann man mit den oben genannten Skriptsprachen gut vermeiden. -- ------------------------------------------------------------------------------------ Thilo Gramlich Thilo (a dot) Gramlich (an at symbol) aktivanet (a dot) de
*** Tol
Wie gehe ich am besten vor, wenn ich bei bestimmten Dateien im Filesystem was verändern möchte?
[...]
Vermute mal, das wirde ne tolle Mischung aus find, pipes und greps. Aber da bin ich noch nicht sooo firm drin. Vorallem das "replace" macht mir noch Schwierigkeiten.
willst du dafür ne GUI? dann schaue dir mal [1] an. micha [1] http://regexxer.sourceforge.net/
Hallo, Am Tue, 10 Feb 2004, Tol schrieb:
Wie gehe ich am besten vor, wenn ich bei bestimmten Dateien im Filesystem was verändern möchte? zB. das body TAG aller HTML und PHP Seiten. Suche nach <body> und ersetze durch <body color="#aabbcc">
==== UNGETESTET!!! Erst verstehen und testen! ==== OIFS="$IFS"; IFS=" "; find . -maxdepth 1 -iname "*.html" | while read name; do if test -e "${name}.bak"; then echo "skipping $name: file exists" >&2; else cp "${name}" "${name}.bak"; sed 's,<body>,<body bgcolor="#aabbcc">,g' \ "${name}.bak" > "$name"; fi done; IFS="$OIFS" ==== -dnh -- 41: Internet Das von President Gates erfundene Computernetz. (Kristian Köhntopp)
*** Tol (linux@recordcaster.de) schrieb heute in suse-linux:
[...] Wie gehe ich am besten vor, wenn ich bei bestimmten Dateien im Filesystem was verändern möchte? zB. das body TAG aller HTML und PHP Seiten. Suche nach <body> und ersetze durch <body color="#aabbcc">
Mit "find" solltest Du anhand des Dateinamens (beispielsweise "-type f -name \"*.html\") einschränken, welche Dateien überhaupt für eine Bearbeitung in Betracht kommen. Mit einem geeignet eingebundenen "grep" (beispielsweise "-exec fgrep -q \"<body>\" {} \;") kannst Du weiter einschränken, welche Files Du bearbeiten mußt und bei welchen das Anfassen vergebliche Liebesmüh' wäre. Die gefundenen Namen kannst Du dann in ein "xargs" pipen, welches einen "sed" (beispielsweise "sed -e \ 's/<body>/
/g'") mit geeigneten Umleitungen aufruft. Ein ebenfalls angeregter "awk" würde nur "sed" ersetzen können, ist aber im Vergleich zu "sed" IMHO unnötig "mächtig" (siehe auch die Größe der Binaries). _Jedes_ File unterhalb eines entsprechenden Verzeichnisses zu bearbeiten wäre IMHO ähnlicher Overkill. "perl" für das finden der zu bearbeitenden Files wäre IMHO ebenfalls und erneut Overkill.[...]
MfG Henning Hucke -- Heute habe ich mal etwas probiert. Wie es ist, ohne Sex, Drogen und Computer auszukommen. Tja - es war die härteste Viertelstunde meines Lebens ;). Geklaut aber toll. (Uuups. Es ist schon wieder passiert :-})
Am Dienstag, 10. Februar 2004 18:03 schrieb Henning Hucke:
*** Tol (linux@recordcaster.de) schrieb heute in suse-linux:
[...] Wie gehe ich am besten vor, wenn ich bei bestimmten Dateien im Filesystem was verändern möchte? zB. das body TAG aller HTML und PHP Seiten. Suche nach <body> und ersetze durch <body color="#aabbcc"> [...] Ein ebenfalls angeregter "awk" würde nur "sed" ersetzen können, ist aber im Vergleich zu "sed" IMHO unnötig "mächtig" (siehe auch die Größe der Binaries). _Jedes_ File unterhalb eines entsprechenden Verzeichnisses zu bearbeiten wäre IMHO ähnlicher Overkill. "perl" für das finden der zu bearbeitenden Files wäre IMHO ebenfalls und erneut Overkill.
Zu awk ACK - zu Perl: hast Du mal Zeiten gemessen, wenns um richtig große Mangen von Dateien geht? Wenn man Perl einsetzt, dann natürlich nicht nur zum Finden, sondern auch zum Ändern derselben. Dein letzter Satz ist Unsinn. Jan
Mit einem geeignet eingebundenen "grep" (beispielsweise "-exec fgrep -q \"<body>\" {} \;") kannst Du weiter einschränken, welche Files Du bearbeiten mußt und bei welchen das Anfassen vergebliche Liebesmüh' wäre.
Naja, immerhin müssen die Files auch damit geöffnet werden, um festzustellen, ob eine Ersetzung vorgenommen werden muß oder eben nicht. Reingucken muß ich eh. Dann mach' ich's doch besser auf und durchsuche es direkt. Wird was gefunden --> ersetzen, und die Datei speichern. Wird nix gefunden --> weiter mit nächster Datei. Oder hab' ich was nicht verstanden?
[...] Die gefundenen Namen kannst Du dann in ein "xargs" pipen, welches einen "sed" (beispielsweise "sed -e \ 's/<body>/
/g'") mit geeigneten Umleitungen aufruft.
Ui ui ui, Ge-grep-pe und ge-pipe ohne Ende. Brrrr ... ;-)
[...] ähnlicher Overkill. "perl" für das finden der zu bearbeitenden Files wäre IMHO ebenfalls und erneut Overkill.
Hm... Wenn ein Skript doch mal da ist, kann man's immer wieder verwenden. Einfach nur die Strings ändern, und laufen lassen. Mein Vorschlag: (Skript als "replace.pl" speichern, $search und $replace anpassen und mit "perl replace.pl" in dem Verzeichnis laufen lassen, das durchsucht werden soll) ----- snip ------------------------- #!/usr/bin/perl ############################################### # # Skript "replace.pl" durchsucht rekursiv alle # Dateien und Verzeichnisse, und ersetzt # gegebenenfalls $search durch $replace # ############################################### # # Such-/Ersetzungsstrings $search = "irgendwas"; $replace = "das soll rein"; # ############################################### # und hier, welche Dateiendungen gesucht # werden sollen (Wildcards sind möglich) $extension=".htm*"; # ############################################### use Time::Local; use File::stat; use File::Find; $rtot=0; print "\nScanning $extension files ... \n\n"; @ARGV = ('.') unless @ARGV; find(\&filesearch, @ARGV); print "\n$i $extension files found, $rtot replacements made!\n\n"; sub filesearch { my (@source,@target,@file)=(); $tmp = $File::Find::name;(@file)=split(/\//,$tmp); if (-f && $file[-1] && $file[-1] =~ /$extension/ && $file[-1] !~ /^replace\.pl$/){ $i++; print " $i: Opening $tmp ... "; open SOURCE,"<$file[-1]"; @source=<SOURCE>; close SOURCE; $r=0; foreach (@source) { if ($_ =~ /\Q$search\E/){ $r++;$rtot++; $_ =~ s/$search/$replace/g; } push @target,$_; } close TARGET; if ($r > 0) { open TARGET, ">$file[-1]"; print "--> replacements: $r\n"; print TARGET @target; close TARGET; } else { print "nothing to do\n"; } } } ----- snap ------------------------- Das Skript ist bei mir schon seit Jahren im Einsatz, und hat mir schon ziemlich viel Arbeit abgenommen. Wichtig ist, das Skript wirklich als "replace.pl" abzulegen. Heißt es anders, durchsucht es sich selber. Wer will kann ja noch diese nette "basename"-Abfrage einbauen. Ciao Dirk
Am Mittwoch, 11. Februar 2004 11:29 schrieb Dirk: [...]
Hm... Wenn ein Skript doch mal da ist, kann man's immer wieder verwenden. Einfach nur die Strings ändern, und laufen lassen.
Mein Vorschlag:
(Skript als "replace.pl" speichern, $search und $replace anpassen und mit "perl replace.pl" in dem Verzeichnis laufen lassen, das ^^^^ nicht notwendig, Du hast ja eine Shebang-Zeile am Anfang.
durchsucht werden soll)
----- snip ------------------------- #!/usr/bin/perl ############################################### # # Skript "replace.pl" durchsucht rekursiv alle # Dateien und Verzeichnisse, und ersetzt # gegebenenfalls $search durch $replace # ###############################################
# hier sollte noch mindestens: use strict; use warnings; # rein, damit Du Fehler auch sehen kannst und zu sauberer # Deklaration der Variablen gezwungen wirst. # Dann kriegst Du folgendes zu sehen: <schnipp> Global symbol "$search" requires explicit package name at ./replace.pl line 18. Global symbol "$replace" requires explicit package name at ./replace.pl line 19. Global symbol "$extension" requires explicit package name at ./replace.pl line 24. BEGIN not safe after errors--compilation aborted at ./replace.pl line 28. <schnapp> # Du arbeitest in wildem Mix mit Daklarationen, die eine # Gültigkeit definieren (my) und mit solchen globalen Deklarationen. # Das ist unsauber, Du merkst nicht, wenn Du vorher definierte # Variablen überschreibst.
# # Such-/Ersetzungsstrings $search = "irgendwas"; $replace = "das soll rein"; # ############################################### # und hier, welche Dateiendungen gesucht # werden sollen (Wildcards sind möglich) $extension=".htm*";
# diese Extension matcht auf alles, was im Dateinamen ein Muster
# der Form: <beliebiges Zeichen>ht
# ###############################################
use Time::Local; use File::stat; use File::Find;
$rtot=0; print "\nScanning $extension files ... \n\n"; @ARGV = ('.') unless @ARGV; find(\&filesearch, @ARGV); print "\n$i $extension files found, $rtot replacements
# siehe oben: durch die fehlende Deklaration und Initialisierung # von $i kriegst Du hier ne merkwürdige Meldung, wenn keine # Dateien gefunden werden.
made!\n\n";
sub filesearch { my (@source,@target,@file)=(); $tmp = $File::Find::name;(@file)=split(/\//,$tmp);
# 1 Anweisung / Zeile, das ist sauberer Stil # Warum ein Array @file, wenn Du nur die Dateinamen brauchst? # nimm basename
if (-f && $file[-1] && $file[-1] =~ /$extension/ && $file[-1]
# ^^^^^^^^^^^^^^^ was soll das machen? Meinst Du nicht eher: if (-f $file[-1] && $file[-1] =~ /$extension/ && $file[-1] # außerdem sollte man hier tatsächlich nach der _Endung_ suchen: if (-f $file[-1] && $file[-1] =~ /$extension$/ && $file[-1]
!~ /^replace\.pl$/){ $i++; print " $i: Opening $tmp ... "; open SOURCE,"<$file[-1]";
# knallt, wenn Du kein Recht hast, die Datei zu lesen. # Abfangen!
@source=<SOURCE>; close SOURCE; $r=0; foreach (@source) { if ($_ =~ /\Q$search\E/){
# David hatte Dich in der anderen Mail schon drauf hingewiesen, $_ # ist meist Default. Hier geht also auch kürzer: if (/\Q$search\E/){
$r++;$rtot++;
# 1 Anweisung / Zeile, das ist sauberer Stil
$_ =~ s/$search/$replace/g;
s/$search/$replace/g;
} push @target,$_; } close TARGET;
# Du machst hier TARGET zu, ohne es vorher zu öffnen. Warum?
if ($r > 0) { open TARGET, ">$file[-1]";
# knallt, wenn Du kein Recht hast, die Datei zu schreiben. # Abfangen!
print "--> replacements: $r\n"; print TARGET @target; close TARGET; } else { print "nothing to do\n"; } } } ----- snap -------------------------
Das Skript ist bei mir schon seit Jahren im Einsatz, und hat mir schon ziemlich viel Arbeit abgenommen.
So? Kann ich mir nicht richtig vorstellen, es sei denn, Du hast bisher großes Glück mit den Dateinamen und -rechten gehabt. ;-)
Wichtig ist, das Skript wirklich als "replace.pl" abzulegen. Heißt es anders, durchsucht es sich selber. Wer will kann ja noch diese nette "basename"-Abfrage einbauen.
Nicht nur basename, auch dirname, ggf. Pfad des Scripts gegen die Pfade prüfen - kann ja sein, dass es nicht nur 1 replace.pl gibt und eine Bearbeitung durchaus gewollt ist. Jan
participants (7)
-
David Haller
-
Dirk
-
Henning Hucke
-
Jan.Trippler@t-online.de
-
Michael Meyer
-
Thilo Gramlich
-
Tol