User-Home kopieren, Einzeiler für Suchen&Ersetzen gesucht
User-Home kopieren, Einzeiler für Suchen&Ersetzen gesucht
Moin Leute,
um die Einrichtung der Xfce-Oberfläche für einen neuen User zu erleichtern, will ich einige der Files und Verzeichnisse unter /home/USERALT/ nach /home/USERNEU/ kopieren. Dort muss ich natürlich UID/GID anpassen. Das ist vergleichsweise leicht und sollte hiermit abgedeckt sein:
Erst von USERALT nach USERNEU kopieren, dann in /home/USERNEU folgendes machen:
find . -user 1100 -exec chown 1111 {} \;
find . -group 1100 -exec chgrp 1111 {} \;
Oder, noch einfacher:
chown -R USERNEU:USERNEU *
Mein Problem sind die kopierten Dateien: darin befindet sich oftmals ein Pfad, in welchem der User als Teil des Pfad steht. Das ist beispielsweise bei gkrellm so, wird aber bei vielen anderen config-files nicht anders sein, dass dort eine Zeile a la
home=/home/USERALT
drinsteht.
Wie kann ich nun mit einer ähnlichen Zeile wie oben genannt Suchen&Ersetzen machen?
Suche in allen Files ab&inklusive Standort (.) nach Zeichenkette USERALT und ersetze sie durch Zeichenkette USERNEU
lautet die Aufgabe.
Kann man sowas als kurzen Einzeiler mit sed oder egrep oder sowas lösen?
um die Einrichtung der Xfce-Oberfläche für einen neuen User zu erleichtern, will ich einige der Files und Verzeichnisse unter /home/USERALT/ nach /home/USERNEU/ kopieren. Dort muss ich natürlich UID/GID anpassen. Das ist vergleichsweise leicht und sollte hiermit abgedeckt sein:
Erst von USERALT nach USERNEU kopieren, dann in /home/USERNEU folgendes machen:
find . -user 1100 -exec chown 1111 {} \;
find . -group 1100 -exec chgrp 1111 {} \;
Oder, noch einfacher:
chown -R USERNEU:USERNEU *
Mein Problem sind die kopierten Dateien: darin befindet sich oftmals ein Pfad, in welchem der User als Teil des Pfad steht. Das ist beispielsweise bei gkrellm so, wird aber bei vielen anderen config-files nicht anders sein, dass dort eine Zeile a la
home=/home/USERALT
drinsteht.
Wie kann ich nun mit einer ähnlichen Zeile wie oben genannt Suchen&Ersetzen machen?
Suche in allen Files ab&inklusive Standort (.) nach Zeichenkette USERALT und ersetze sie durch Zeichenkette USERNEU
lautet die Aufgabe.
Kann man sowas als kurzen Einzeiler mit sed oder egrep oder sowas lösen?
Re: User-Home kopieren, Einzeiler für Suchen&Ersetzen gesuch
Ergänzung: wenn dann noch aufgelistet würde, welche files verändert wurden, wäre das ganze perfekt!
Re: User-Home kopieren, Einzeiler für Suchen&Ersetzen gesuch
Deine Frage ist ja nun schon ein paar Tage alt und vermutlich hast Du Dein Problem schon irgendwie gelöst, aber vielleicht kannst Du es ja doch noch gebrauchen oder es hilft zumindest in Zukunft jmd. weiter: Ich würde eine Kombination von find, grep und sed einsetzen, um das Problem zu lösen:
Dabei geschieht folgendes:
Luka
Code: Alles auswählen
$ for i in $( find . -type f -print0 | xargs --null grep -l "USERALT" ) ; do
> sed -i 's/USERALT/USERNEU/g' $i && echo $i
> done
- die for-Schleife weist der Variable $i nacheinander die Ergebnisse der Befehlsersetzung $(...) zu und führt für jedes die Befehle zwischen do ... done aus
- innerhalb der Befehlsersetzung $(...)
- sucht find vom aktuellen Verzeichnis aus (.) nach allen regulären Dateien (-type f), wobei die Ergebnisse nicht mit einem Leerzeichen, sondern mit einem Null-Zeichen getrennt werden (-print0), so dass keine Gefahr besteht, dass im Folgenden ein Dateiname mit Leerzeichen als mehrere Dateien behandelt wird
- die Ausgabe des vorigen Befehls wird per Pipe (|) als Eingabe an den nächsten Befehl weitergereicht
- xargs fügt die Eingabe zu einer Argumentenliste zusammen, mit der es den Befehl ausführt, der auf seine eigenen Optionen folgt. Dabei berücksichtigt es, dass die Eingabe mit Null- statt Leerzeichen getrennt ist (--null)
- grep durchsucht die Dateien nach dem Muster USERALT, wobei es statt der übereinstimmenden Zeilen nur die Namen derjenigen Dateien ausgibt, die eine oder mehrere Übereinstimmungen aufweisen (-l)
- innerhalb der do ... done-Schleife
- ersetzt der Streameditor sed alle Vorkommen von USERALT durch USERNEU ('s/USERALT/USERNEU/g', wobei er statt der Standardeingabe eine Datei als Datenstrom einliest (-i), den es Zeile für Zeile durchscannt. Bei der Datei handelt es sich um den jeweiligen Wert der Variable $i innerhalb der aktuellen Schleife.
[*] Wenn der vorherige Befehle ohne Fehler ausgeführt wurde, wird der folgende Befehl ebenfalls ausgeführt (&&) (wobei sed auch dann einen fehlerfreien Durchlauf signalisiert, wenn es keine Ersetzungen vorgenommen hat - aber da grep ja bereits die Dateien herausgefischt hat, in denen das Muster USERALT vorkommt, können wir uns auf die Ausgabe dennoch verlassen)
- ersetzt der Streameditor sed alle Vorkommen von USERALT durch USERNEU ('s/USERALT/USERNEU/g', wobei er statt der Standardeingabe eine Datei als Datenstrom einliest (-i), den es Zeile für Zeile durchscannt. Bei der Datei handelt es sich um den jeweiligen Wert der Variable $i innerhalb der aktuellen Schleife.
- um sicherzugehen, dass das Suchmuster nicht in manchen Dateien in ganz anderen Zusammenhängen erscheint, in denen keine Ersetzung erwünscht ist, würde ich zuerst mit folgendem Befehl überprüfen, was grep genau aufspürt:
Code: Alles auswählen
$ find . -type f -print0 | xargs --null grep --color=auto "USERALT"
- sed und grep sind in dieser Form beide case sensitive, d.h. im Suchmuster ist auf Groß- und Kleinschreibung zu achten. Beide Befehle verfügen aber auch über Optionen, um die Zeichengröße(? ) zu ignorieren.
- Warum xargs und nicht find ... -exec? Da du möglicherweise recht viele Ergebnisse haben wirst, ist xargs schneller, da es mehrere Ergebnisse zu einer Kette von Argumenten zusammenfasst, während exec für jedes Ergebnis einen eigenen Prozess aufruft (wobei der Geschwindigkeitsunterschied wahrscheinlich nicht ins Gewicht fällt). Praktischerweise achtet xargs dabei auch gleich auf die Längenbebegrenzung der Befehlszeile in Deiner aktuellen Umgebung und führt falls nötig mehrere Prozesse mit Argumenten aus (aber eben nur so viele, wie tatsächlich benötigt werden).
- grep und sed sind recht mächtige Such- bzw. Prozessierungstools, mit denen Du über reguläre Ausdrücke auch nach sehr komplexen Mustern suchen kannst. Insbesondere sed kann noch sehr viel mehr als suchen und ersetzen. ich empfehle man sed zu überfliegen und info sed zum Vertiefen. Außerdem gibt es einige gute Online-Tutorials ...
Luka
Re: User-Home kopieren, Einzeiler für Suchen&Ersetzen gesuch
Schoener Post, du hast da echt Aufwand reingesteckt . Trotzdem wuerde ich gerne anmerken, dass die Schleife bei Treffern mit Dateinamen mit Whitespaces explodiert. Also wenn grep jetzt in einer Datei /foo\ bar/baz fuendig wird, bekommt das sed einmal /foo und dann bar/baz, was nicht im Sinne des Erfinders ist. Stattdessen wuerde ich gleich mit Nullbytes und xargs weitermachen:(kleine Aenderungen: ./ ist default, kann also weggelassen werden; -0 ist kuerzer als--null; -print0 von grep heisst -Z.) Bisschen bloed ist nur, dass man keine Liste der geaenderten Dateien bekommt, aber die kann man ja im Vorfeld betrachten. Uebrigens ist das potenziell 'ne groessere Menge an Daten, die auf's Terminal geschrieben werden, da wuerde ich less mit --RAW-CONTROL-CHARS nachschalten:(--color laesst sich abkuerzen und muss auf always stehen, weil's wegen der Pipe per default never ist.)
Wie sinnvoll das rohe Ersetzen bei SQLite-Datenbanken oder sonstigen BLOBs ist, kann man sich auch fragen... oder wenn da CRC oder sonstige Pruefsummen draufliegen. Aber da ist dann der TE schuld, denn er will's so haben .
Willkommen im Forum!
Gruss Cae
Code: Alles auswählen
$ find -type f -print0 | xargs -0 grep -lZ 'USERALT' | xargs -0 sed -i 's/USERALT/USERNEU/g'
Code: Alles auswählen
$ find -type f -print0 | xargs -0 grep --col=always "USERALT" | less -R
Wie sinnvoll das rohe Ersetzen bei SQLite-Datenbanken oder sonstigen BLOBs ist, kann man sich auch fragen... oder wenn da CRC oder sonstige Pruefsummen draufliegen. Aber da ist dann der TE schuld, denn er will's so haben .
Willkommen im Forum!
Gruss Cae
If universal surveillance were the answer, lots of us would have moved to the former East Germany. If surveillance cameras were the answer, camera-happy London, with something like 500,000 of them at a cost of $700 million, would be the safest city on the planet.
—Bruce Schneier
Re: User-Home kopieren, Einzeiler für Suchen&Ersetzen gesuch
Wie wäre es mit einem bind-mount von /home/userneu auf /home/useralt?
Dann würdest du zwar weiterhin mit alten Pfaden arbeiten, aber der Drops ist nach wenigen Sekunden gelutscht…
Dann würdest du zwar weiterhin mit alten Pfaden arbeiten, aber der Drops ist nach wenigen Sekunden gelutscht…
Re: User-Home kopieren, Einzeiler für Suchen&Ersetzen gesuch
Wow, es kommen ja doch noch Antworten
@ThorstenS: Ich glaube, du hast das Grundproblem nicht verstanden, einfach nochmal im ersten post nachlesen
Meine Lösung sieht zwischenzeitlich so aus:
erstdann
Wenn es gut aussieht, einfach das zweite "echo" weglöschen.
@ThorstenS: Ich glaube, du hast das Grundproblem nicht verstanden, einfach nochmal im ersten post nachlesen
Meine Lösung sieht zwischenzeitlich so aus:
erst
Code: Alles auswählen
chown -R USERNEU:USERNEU *
Code: Alles auswählen
find . -type f | while read g; do echo "Bearbeite $g"; echo sed -i s/USERALT/USERNEU/g "$g"; done
Re: User-Home kopieren, Einzeiler für Suchen&Ersetzen gesuch
Nein, er/sie hat sogar eine sehr geniale Loesung, um das Problem der unterschiedlichen Pfade erst gar nicht entstehen zu lassen: Das $HOME wird einfach an Ort und Stelle mit dem des "Testbenutzers" ersetzt. Der Pfad bleibt gleich, die Daten des "Produktivbenutzers" unangetastet. Wobei die "beiden Benutzer" in diesem Szenario sogar einfach derselbe Benutzer ist.dirk11 hat geschrieben:@ThorstenS: Ich glaube, du hast das Grundproblem nicht verstanden, einfach nochmal im ersten post nachlesen
Gruss Cae
If universal surveillance were the answer, lots of us would have moved to the former East Germany. If surveillance cameras were the answer, camera-happy London, with something like 500,000 of them at a cost of $700 million, would be the safest city on the planet.
—Bruce Schneier
Re: User-Home kopieren, Einzeiler für Suchen&Ersetzen gesuch
Ich hätt' ja lieber eine Kommentierung zu meinem Einzeiler.
Aber Cae, was wäre daran "genial"? Ehrlich gesagt verstehe ich das nicht. Es gibt keinen "Testbenutzer", ich kopiere nur bestimmte .*** (noch nicht einmal alle) eines bestimmten Benutzers, um z.B. die Einstellungen des Panel zu übernehmen. Der Benutzer soll die danach natürlich nach Belieben verändern können, ich will nur eine einheitliche Grundeinstellung erreichen.
Aber Cae, was wäre daran "genial"? Ehrlich gesagt verstehe ich das nicht. Es gibt keinen "Testbenutzer", ich kopiere nur bestimmte .*** (noch nicht einmal alle) eines bestimmten Benutzers, um z.B. die Einstellungen des Panel zu übernehmen. Der Benutzer soll die danach natürlich nach Belieben verändern können, ich will nur eine einheitliche Grundeinstellung erreichen.
-
- Beiträge: 134
- Registriert: 03.02.2011 11:11:21
- Lizenz eigener Beiträge: MIT Lizenz
- Wohnort: Frankfurt
Re: User-Home kopieren, Einzeiler für Suchen&Ersetzen gesuch
Beachtung von Wortgrenzen im RegEx ist zu empfehlen, sonst wird schnell z.B. beidirk11 hat geschrieben:Code: Alles auswählen
... sed -i s/USERALT/USERNEU/g "$g"
Code: Alles auswählen
sed -i s/hans/bert/g
Re: User-Home kopieren, Einzeiler für Suchen&Ersetzen gesuch
Naja, bei langen Befehlszeilen und unklarem Vorwissen finde ich es immer blöd, wenn nicht erklärt wird, was da passiert (wobei sich das mit dem Vorwissen inzwischen auch für mich aufgeklärt hat, hätte mir das zumindest für den OP also sparen können). Wenn es aber so (zu) ausführlich wird, wie hier, ist das immer ein klares Zeichen, dass ich entweder gerade jede Menge freie Zeit und Lust habe, sie in meinem "virtuellen Hobbykeller" zu verbringen, oder gar keine Zeit habe und vor einer wirklich dringenden Aufgabe, bei deren Lösung ich nicht weiterkomme, in den virtuellen Hobbykeller flüchte.Cae hat geschrieben:Schoener Post, du hast da echt Aufwand reingesteckt .
Aber danke für Deine Reaktion - grep -Z war mir nicht bewusst und die --RAW-CONTROL-CHARS für less hatte ich mir immer schon gewünscht und bisher übersehen.
Stimmt! Oh mann! Jetzt springt es geradezu ins Auge Das hätt ich wohl besser mal testen sollen ... (Wieso gibt es denn hier kein :werdrot: ?)Also wenn grep jetzt in einer Datei /foo\ bar/baz fuendig wird, bekommt das sed einmal /foo und dann bar/baz, was nicht im Sinne des Erfinders ist.
Jep. Trotzdem dachte ich mir als ich das gestern Abend las, dass das doch auch in einem Befehl und auf dem Weg, den ich oben eingeschlagen hatte, zu machen sein müsste: "da gab es doch noch die Systemkonstante $IFS (Internal Field Seperator) und damit kann ich die Zeile oben doch bestimmt mal eben ---" - und schon waren wieder 2 Stunden in meinem "Hobbykeller" mit Stöbern in manpages und Ausprobieren rum. Denn sobald ich versuchte, den verfluchten IFS dazu zu kriegen, einen Null-Character oder nicht-SPACE-Whitespace zu akzeptieren, wurde es einfach ignoriert (ok, zwischendurch habe ich auch versucht, andere Wege einzuschlagen). Schließlich habe ich also doch im Netz nachgeschaut, wie man den $IFS rumkriegt, was zu meinem zweiten -Moment führte (denn zumindest auf IFS=$(echo -en "\n") hätte ich eigentlich selbst kommen können). Danach war es dann einfach:Stattdessen wuerde ich gleich mit Nullbytes und xargs weitermachen: [...] Bisschen bloed ist nur, dass man keine Liste der geaenderten Dateien bekommt, aber die kann man ja im Vorfeld betrachten.
Code: Alles auswählen
$ IFS=$'\n\t' ; for i in $(find . -type f -print0 | xargs --null grep -l "USERALT") ; do
> sed -i 's/USERALT/USERNEU/g' $i && echo $i ;
> IFS=$' \t\n' # aus Default zurücksetzen
> done
Aber das eh nur um noch einen möglichen "Lösungsweg" darzustellen. Für die praktische Verwendung ist Deine Vorgehensweise nicht nur übersichtlicher sondern wohl auch wesentlich schneller (insb. bei großen Datenmengen). Im übrigen könnte man auch da noch mit tee die grep-Ausgabe in eine Datei umleiten um sie dann am Ende auszugeben:
Code: Alles auswählen
$ find -type f -print0 | xargs -0 grep -lZ 'USERALT' | tee temp.log | xargs -0 sed -i 's/USERALT/USERNEU/g' ; cat temp.log | tr "\0" "\n" | less
Soweit dazu ...
MerciWillkommen im Forum!
Luca
Re: User-Home kopieren, Einzeiler für Suchen&Ersetzen gesuch
Oh ja, stimmt! Abernewdeb hat geschrieben:dirk11 hat geschrieben: Beachtung von Wortgrenzen im RegEx ist zu empfehlen
Code: Alles auswählen
... sed -i s/USERALT/USERNEU/g "$g"
Code: Alles auswählen
sed -i 's/\bUSERALT\b/USERNEU/g' file
Re: User-Home kopieren, Einzeiler für Suchen&Ersetzen gesuch
Nein, hättest du nicht! Vielen Dank für die ausführlichen Erläuterungen, damit ist auch mir einiges klarer geworden!luka hat geschrieben:Naja, bei langen Befehlszeilen und unklarem Vorwissen finde ich es immer blöd, wenn nicht erklärt wird, was da passiert (wobei sich das mit dem Vorwissen inzwischen auch für mich aufgeklärt hat, hätte mir das zumindest für den OP also sparen können).