ImpressumFrank Seitz Wassermühlenstr. 2 25436 Uetersen E-Mail: fsfseitz.de Tel.: +49-176-78243503 Alle Artikel Inhaltsverzeichnis Rechtliche Hinweise Code auf GitHub Code auf meta::cpan KategorienAbonnieren |
Mittwoch, 21. September 2022Perl: Mehrzeilige Ersetzung auf DateienIn Dateien eines Verzeichnisbaums wollen wir eine mehrzeilige Ersetzung vornehmen. Unter Nutzung von Perl geht dies mit einem Einzeiler: $ find DIR ... | xargs perl -0777 -p -i -E 's/REGEX/REPLACEMENT/gms'
Hierbei ist REGEX ein Regulärer Ausdruck, der Text über mehreren Zeilen matchen kann. Wie funktioniert der Aufruf? Perl verarbeitet die Dateien, die von xargs(1) als Argumente übergeben werden, und behandelt sie gemäß den angegebenen Optionen:
Beispiel Entferne im Verzeichnisbaum DIR die Inline-Dokumentation (POD) aus allen .pm-Dateien: $ find DIR -name '*.pm' | xargs perl -0777 -p -i -E 's/^=[a-z].*?^=cut\n//gms'
Samstag, 9. Februar 2019Shell: Umgebung universell nutzbar aufsetzenFür die Ausführung von Programmen ist es oft notwendig, dass bestimmte Umgebungsvariablen gesetzt sind. Dies kann allgemeine Variablen betreffen, wie z.B. den Suchpfad PATH oder programmspezifische Variablen, wie z.B. ORACLE_HOME. Die Frage ist, wie man eine Shell-Umgebung aufsetzt, so dass diese möglichst universell nutzbar ist, insbesondere, wenn Programme auch von außerhalb der eigenen interaktiven Sitzung, z.B. via cron, sudo oder ssh ausgeführt werden sollen. Die Shell (bash, ksh, sh) führt bei jedem Login die nutzerspezifische Datei .profile aus. Werden in dieser Datei alle Environment-Variablen gesetzt (und exportiert), kann die Umgebung leicht in anderen Kontexten genutzt werden. Die Variablen in einer rc-Datei (.bashrc oder .kshrc) zu setzen ist verkehrt, da der Inhalt einer rc-Datei ausschließlich bei interaktiven Sitzungen ausgeführt wird und daher ausschließlich Definitionen enthalten sollte, die für eine Benutzerinteraktion mit der Shell relevant sind (Beispielsweise: Aussehen des Prompt, Aliase, Länge der History, Farben für ls(1), usw.). TTY-Login, SSH LoginDies ist der normale Anwendungsfall. Eine Login-Shell wird gestartet und im Zuge dessen .profile ausgeführt. Ausführung eines Remote-Kommandos per SSHDas Remote-Kommando ersetzt in diesem Fall die Login-Shell. Wir sorgen mit bash -l dafür, dass die Login-Umgebung hergestellt wird: $ ssh USER@HOST "bash -lc 'COMMAND'" X11 Terminal Window LoginHier ist es wichtig, dass beim Öffnen des Terminals eine Login-Shell ausgeführt wird. Ggf. ist es nötig, hierfür eine Option in den Einstellungen zu aktivieren. In den Einstellungen des Xfce Terminals heißt die Option "Run command as login shell", ist per Default dekativert und sollte aktiviert werden. sudoBei sudo sorgt die Option -i dafür, dass das Kommando an eine Login-Shell übergeben wird: $ sudo -iu USER COMMAND cron, eigene crontabWie bei der Ausführung eines Remote-Kommandos per ssh sorgen wir mit bash -l dafür, dass die Login-Umgebung vor Ausführung des Kommandos hergestellt wird. * * * * * bash -lc COMMAND cron, fremde crontabAnstelle der bash nutzen wir sudo (wie oben): * * * * * sudo -iu USER COMMAND Freitag, 9. Oktober 2015Grep: Finde in Dateibaum Worte eines bestimmten MustersFinde innerhalb des Dateibaums DIR alle Vorkommen des Wortmusters REGEX und gib die Wortliste sortiert aus (GNU grep): $ grep -oPhr REGEX DIR | sort | uniq
Soll die Menge der Dateien näher eingeschränkt werden, lässt sich dies durch ein vorgeschaltetes find erreichen (Option -r bei grep entfällt dann): $ find DIR -type f -print0 | xargs -0 grep -oPh REGEX | sort | uniq
AnwendungsfallFinde in Dateibaum app mit Perl-Quelltexten die Namen aller verwendeten Klassen, die mit "R1::" beginnen: $ grep -oPhr 'R1::[:\w]+' app | sort | uniq R1::AppHome R1::Array R1::CheckValue R1::ClassLoader R1::Config R1::Dbms::Database ... LinksMittwoch, 22. Juli 2015Globale in-place Textersetzung mit sed oder PerlMitunter möchte man einen Text oder ein Muster global über mehreren Dateien FILE ... ersetzen. Unter Unix/Linux geht das am einfachsten mit sed (GNU): $ sed -i s/PATTERN/REPLACEMENT/g FILE ... Das Gleiche, angewendet auf einen Dateibaum DIR: $ find DIR -type f | xargs sed -i s/PATTERN/REPLACEMENT/g Perl bietet die sed-Funktionaltät mit einer ähnlich einfachen Kommandozeile: $ perl -pi -e s/PATTERN/REPLACEMENT/g FILE ... Der Vorteil von Perl gegenüber sed ist dessen leistungsfähigere Regex-Engine. Bei GNU sed lassen sich mit Option -r "Extended Regular Expressions" einschalten (die eher an Perl Regexes heranreichen). WICHTIG: Die Ersetzungsoperation wird zeilenweise angewendet, d.h. eine Ersetzung über Zeilengrenzen hinweg ist nicht möglich. LinksSonntag, 24. Mai 2015Unix Epoch in lesbare Zeitangabe wandeln und umgekehrtUm einen Unix Epoch-Wert (Sekunden seit 1.1.1970 0 Uhr UTC) mit Shell-Mitteln in eine lesbare Zeitangabe (lokale Zeitzone) zu wandeln, kann man sich des Kommandos date bedienen: $ date -d @1406546442 Mo 28. Jul 13:20:42 CEST 2014 Dasselbe in einer besser strukturierten Darstellung: $ date -d @1406546442 '+%F %T %z' 2014-07-28 13:20:42 +0200 Hierbei ist: %F - Datum %T - Uhrzeit %z - Zeitzone als hhmm-Offset Soll die Ausgabe in einer anderen als der lokalen Zeitzone erfolgen, wird die Environment-Variable TZ entsprechend gesetzt (hier Ausgabe in UTC): $ TZ=UTC date -d @1406546442 '+%F %T %z' 2014-07-28 11:20:42 +0000 Dasselbe im ISO-8601 Datumsformat (sekundengenau): $ date -d @1406546442 --iso-8601=seconds 2014-07-28T13:20:42+0200 Die Umkehrung - also die Wandlung einer lesbaren Zeitangabe (der lokalen Zeitzone, wenn keine angegeben ist, hier: MESZ) in Epoch - ist auch möglich: $ date -d '2014-07-28 13:20:42' +%s 1406546442 Soll die Interpretation in einer anderen Zeitzone als der lokalen Zeitzone erfolgen, kann dies durch Setzen der Environmentvariable TZ erreicht werden: $ TZ=UTC date -d '2014-07-28 13:20:42' +%s 1406553642 # Differenz zu oben: -7200, also minus 2 Stunden gegenüber MESZ Der aktuelle Zeitpunkt als Epoch-Wert: $ date +%s 1406548003 Details siehe date(1) Manpage Samstag, 17. Januar 2015Dateibaum chronologisch sortiert anzeigenMitunter weiß (oder vermutet) man, dass ein Programm Dateien in einen Bereich des Dateisystems schreibt, aber man weiß nicht genau in welche Verzeichnisse und wie die Dateien heißen. Dem lässt sich auf den Grund gehen, indem man sich unmittelbar nach Beendigung des Programms die Pfade des betreffenden Dateibaums chronlogisch nach dem letzten Modifikationszeitpunkt sortiert anzeigen lässt. Unter den letzten Pfaden in der Liste sollten die gesuchten Dateien zu finden sein. Die Unix-Kommandozeile (mit GNU find), die dies leistet, lautet: $ find DIR -type f -printf '%T+ %p\n' | sort Hierbei ist DIR das Wurzelverzeichnis des untersuchten Dateibaums. Für jede Datei wird eine Zeile ausgegeben, bestehend aus der mtime in ISO-ähnlicher Darstellung (%T+) und dem Pfad (%p) der Datei. Details siehe find(1) Manpage Dienstag, 19. Februar 2013Shell: stderr auf Pipe umleiten und andere dup-OperationenEiner der weniger einleuchtenden Shell-Operatoren ist der Operator >&. Den Klassiker, die Umlenkung von stdout und stderr in eine Datei, $ cmd >/tmp/file 2>&1 kennt jeder, der häufiger unter Unix unterwegs ist. Es stellt sich dabei aber immer leicht die Frage: Wie war das nochmal? Muss 2>&1 vor der Umlenkung >/tmp/file stehen? Oder dahinter? Gleichgültig ist die Reihenfolge jedenfalls nicht. Die Beschreibung auf der Bash-Manpage ist recht knapp:
Das heißt, man kann den Operator N>&M als Zuweisung verstehen: Das Ausgabeziel (Terminal, Datei oder Pipe), das seitens des schreibenden Prozesses über Deskriptor M erreicht wird, wird von der Shell (zusätzlich) mit Deskriptor N verbunden. Alles, was der schreibende Prozess auf Desktiptor N schreibt, gelangt somit an das gleiche Ziel wie das, was er auf Deskriptor M schreibt. Liegen mehrere Umlenkungsoperationen vor, werden diese von links nach rechts ausgewertet. Es folgen einige Anwendungsfälle. Stderr und stdout gemeinsam auf eine Pipe lenken$ cmd1 2>&1 | cmd2
Ergebnis: stdout und stderr gehen auf die Pipe. Stderr statt stdout auf eine Pipe lenken$ cmd1 2>&1 >/dev/null | cmd2
Ergebnis: stderr geht auf die Pipe, stdout geht nach /dev/null. Stdout und stderr vertauschen$ cmd 3>&1 1>&2 2>&3 3>&-
Ergebnis: stdout und stderr sind vertauscht. Freitag, 14. Januar 2011Finde Dateinamen mit SonderzeichenFinde in Dateibaum DIR alle Dateinamen mit Sonderzeichen, also mit Zeichen, die nicht im ASCII-Zeichensatz liegen: find DIR | perl -ne "print if /[^[:ascii:]]/" Umlaute und andere Non-ASCII-Zeichen in Dateinamen sind problematisch und sollten vermieden werden, wenn nicht garantiert ist, dass systemweit mit ein und demselben Encoding gearbeitet wird, denn das Encoding eines Dateinamens lässt sich aus diesem nicht herleiten. Freitag, 29. Januar 2010Rsync: Abweichende Rechte einstellenMit der Option -a führt rsync den Abgleich im "Archive Mode" durch, d.h. Symlinks, Devices, Permissions, Ownerschaft usw. werden auf die Zielmaschine transferiert. Was aber, wenn gewisse Unterschiede erforderlich sind, z.B. die Ownerschaft einiger Dateien verschieden sein muss, weil der Owner oder die Group auf der Zielmaschine anders heißen? Beispiel: Die Group des HTTP-Servers heißt auf der einen Maschine "www-data" während sie auf der anderen Maschine "apache" heißt. Über die Group bekommt der HTTP-Server Rechte auf bestimmten Dateien eingeräumt, sie muss also passend zur Maschine gesetzt sein. Solche Differenzen kann rsync nicht auflösen und bietet auch keine Option hierfür. Es lässt sich aber mit einem nachgeschalteten Shell-Skript erreichen, das via ssh auf der Zielmaschine ausgeführt wird: rsync -avz --delete -e ssh DIR1/ USER@HOST:DIR2 ssh USER@HOST CMD Wird CMD in DIR1 abgelegt, wird es durch den rsync-Aufruf mit verwaltet, also automatisch auf dem neusten Stand gehalten. Donnerstag, 21. Januar 2010Verzeichnisse via rsync abgleichenVerzeichnisbaum spiegeln (local => remote)$ rsync -avz --delete DIR1/ USER@HOST:DIR2 Der trailing Slash bei DIR1/ ist wichtig, da sonst DIR1 in dir DIR2 hineinkopiert wird. Die Verzeichnisse können unterschiedlich heißen. Bei Angabe der Option -n wird die Ausführung nur simuliert. Via ssh$ rsync -e ssh -avz --delete DIR1/ USER@HOST:DIR2 Via ssh mit speziellem Port$ rsync --rsh='ssh -p port' -avz --delete DIR1/ USER@HOST:DIR2
(Seite 1 von 1, insgesamt 10 Einträge)
|
Kalender
StatistikLetzter Artikel:
08.07.2024 21:11 157 Artikel insgesamt
Links
|