Reguläre Ausdrücke

Die erste Zeile weist der Shell-Variablen $MUSTER einen regulären Ausdruck zu. Er enthält etliche Backslashes (Rückwärts-Schrägstriche "\"), die ihn unleserlich machen. In einer vereinfachten (und nicht funktionierenden) Darstellung hat der Ausdruck die Form

.*-[0-9][0-9]?.[0-9][0-9]?.20..-.*

Die einzelnen Teile dieses Ausdrucks haben die folgenden Bedeutungen:

  • .*: Der Punkt steht für ein beliebiges Zeichen, und das Sternchen dahinter bedeutet, dass dieses beliebig oft (auch nie) auftreten darf.
  • -: Das ist einfach das Minuszeichen, das in den Beispieldateinamen vor und hinter dem Datum steht.
  • [0-9]: Wie bei den einfacheren Mustern, welche die Shell versteht (siehe oben), steht [0-9] für eine der Ziffern zwischen 0 und 9.
  • [0-9]?: Das angehängte Fragezeichen ändert diesen Teilausdruck ab; es bewirkt, dass hier entweder eines der Zeichen 0--9 oder nichts erwartet wird. (Zusammengefasst steht also [0-9][0-9]? für eine ein- oder zweistellige Zahl.)
  • 20..: Dies ist schließlich das vereinfachte Muster für eine mit 20 beginnende vierstellige (Jahres-)Zahl (wobei 20.. auch auf die Zeichenkette 20th passt).

In dieser Darstellung tauchen Punkte in zwei Bedeutungen auf: einmal als beliebiges Zeichen und einmal als echter Punkt (im Datum zwischen Tag und Monat sowie zwischen Monat und Jahr). Aus diesem Grund verwendet der korrekte reguläre Ausdruck die Darstellung \. für einen "echten" Punkt. Auch das Fragezeichen muss mit einem Backslash versehen werden. Beachtet man diese Regeln, ergibt sich der Ausdruck

.*-[0-9][0-9]\?\.[0-9][0-9]\?\.20..-.*

welcher dem endgültigen Ausdruck schon stärker ähnelt. Was jetzt noch fehlt, sind die zahlreichen öffnenden und schließenden runden Klammern \(...\), welche Teilausdrücke einklammern. Dadurch kann man später die so erkannten Teile separat ansprechen, als "ersten geklammerten Ausdruck", "zweiten geklammerten Ausdruck" usw., in der Notation regulärer Ausdrücke mit \1, \2 usw.

Wenn es nur darum ginge, die Jahreszahl aus dem Dateinamen herauszuholen, würde es ausreichen, diesen Teilausdruck in Klammern zu setzen, also

.*-[0-9][0-9]\?\.[0-9][0-9]\?\.\(20..\)-.*

Da aber auch die restlichen Teile benötigt werden, gibt es hier insgesamt fünf Teilausdrücke (Namensteil vor dem Datum, Tag, Monat, Jahr, Namensteil nach dem Datum), die durch Klammern markiert werden.

Die Befehle hinter der Musterdefinition rufen alle das Kommando sed auf, das reguläre Ausdrücke versteht. Alle Befehle arbeiten ähnlich und entnehmen dem Dateinamen die fünf Teilausdrücke. Wenn also in $NAME anfangs der Wert Brief-Finanzamt-17.3.2012-Kopie.odt steht, dann gilt nach dem Ausführen der Befehle:

$ echo $VORNE; echo $TAG; echo $MONAT; echo $JAHR; echo $HINTEN
Brief-Finanzamt
17
3
2012
Kopie.odt

(Die echo-Kommandos geben die Inhalte der Variablen aus.) Die letzten beiden Befehle (mit test) dienen nur dazu, Tag und Monat mit einer führenden Null zu versehen, falls diese Zahlen einstellig (zwischen 1 und 9) sind; dazu prüft test, ob der Inhalt der Shell-Variablen $TAG bzw. $MONAT kleiner oder gleich 9 (englisch: less or equal, -le) ist.

Nun ist der Dateiname (der in der Variablen $NAME steht) in seine Bestandteile zerlegt, und diese kann man nach Bedarf verwenden, um daraus Verzeichnis- oder neue Dateinamen zu erstellen. Ist das Ziel wieder, die Dokumente in Unterordner der Form JJJJ/MM zu verteilen und dabei noch umzubenennen, könnten sich z. B. die folgenden Befehle anschließen:

mkdir -p $JAHR/$MONAT
mv "$NAME" "$JAHR/$MONAT/$JAHR-$MONAT-$TAG-$VORNE-$HINTEN"

Damit würde die Datei Brief-Finanzamt-17.3.2012-Kopie.odt in 2012-03-17-Brief-Finanzamt-Kopie.odt umbenannt und in den Ordner 2012/03/ verschoben. Die Anführungszeichen sind wieder notwendig, damit Dateinamen mit Leerzeichen keine Probleme verursachen.

Alle Befehle zusammengefasst und mit einer For-Schleife versehen, die einen ganzen Ordner voller Dateien auf geeignete Unterordner aufteilt, finden Sie in Listing 1, dort gibt es zusätzlich noch eine Abfrage (if ...), die dafür sorgt, dass nur wirklich vorhandene Dateinamen bearbeitet werden. Wenn Sie die Code-Zeilen in eine Datei namens script.sh schreiben, können Sie diese mit

. script.sh

(mit einem Punkt und einem Leerzeichen am Anfang des Befehls) ausführen, und alle Dateien landen am gewünschten Ort. Zusätzlich gibt das Script zu jeder bearbeiteten Datei mit echo aus, was es getan hat. Die Muster im Listing wurden gegenüber der Darstellung im Text noch leicht verändert, so dass es auch mit Dateinamen funktioniert, bei denen auf das Datum direkt die Dateiendung folgt.

Listing 1

Verschieben mit regulären Ausdrücken

for NAME in *-{[1-9],[0-3][0-9]}.{[1-9],[01][0-9]}.20??*; doif test "${NAME:0:1}" != '*'; then
    MUSTER='\(.*\)-\([0-9][0-9]\?\)\.\([0-9][0-9]\?\)\.\(20..\)\?\(.*\)'
    VORNE=$(  echo $NAME | sed -e "s|$MUSTER|\1|" )
    TAG=$(    echo $NAME | sed -e "s|$MUSTER|\2|" )
    MONAT=$(  echo $NAME | sed -e "s|$MUSTER|\3|" )
    JAHR=$(   echo $NAME | sed -e "s|$MUSTER|\4|" )
    HINTEN=$( echo $NAME | sed -e "s|$MUSTER|\5|" )
    test $TAG -le 9 && TAG=0$TAG
    test $MONAT -le 9 && MONAT=0$MONAT
    test $HINTEN = "-" && HINTEN=""
    mkdir -p $JAHR/$MONAT
    mv "$NAME" "$JAHR/$MONAT/$JAHR-$MONAT-$TAG-$VORNE$HINTEN"
    echo $NAME '-->' $JAHR/$MONAT/$JAHR-$MONAT-$TAG-$VORNE$HINTENfidone

Die Abbildungen 2 und 3 zeigen ein Beispielszenario mit acht Dokumenten, die zunächst alle im Ordner Dokumente liegen und nach dem Ausführen des Scripts in Unterverzeichnissen von 2011 und 2012 landen.

Abbildung 2: Dateien komplex umbenennen und verschieben – dafür benötigen Sie ein Bash-Script, das mit regulären Ausdrücken arbeitet.
Abbildung 3: Das ist das Wunschergebnis: Die Dokumente liegen jetzt nach Jahren und Monaten getrennt in separaten Ordnern und haben besser sortierbare Namen.

Scanner-Kontrast

Zum Abschluss noch ein einfacheres Beispiel aus dem Bereich der Bildbearbeitung: Wenn Sie gelegentlich unter Linux Dokumente einscannen, haben Sie vielleicht auch das Problem, dass die Scans viel zu dunkel werden; das Papier erscheint dann nicht weiß, sondern dunkelgelb bis bräunlich. Drucken Sie es in dieser Form aus (um eine Kopie zu machen), ist auch der Ausdruck unangenehm dunkel und verschwendet Tinte oder Toner.

Scanprogramme wie XSane oder das in der letzten Ausgabe vorgestellte gscan2pdf [1] erlauben es Ihnen zwar, die Kontrast- und Farbeinstellungen für den Scan zu ändern, aber das müssen Sie bei jedem Programmstart erneut erledigen. Für bereits eingescannte Dokumente können Sie den Kontrast nachträglich mit Gimp oder einer anderen Bildbearbeitung anpassen, was lästig ist, wenn Sie zahlreiche Seiten nachbearbeiten müssen.

Die Shell lässt Sie auch hier wieder schneller arbeiten, wenn Sie das Programm convert aus dem imagemagick- (Ubuntu) bzw. ImageMagick-Paket (OpenSuse) installiert haben: Mit diesem Tool können Sie ebenfalls Kontrast- und Farbkorrekturen vornehmen, ohne dafür die Bilder zunächst zu öffnen. Praktisch ist außerdem, dass Sie auf Wunsch direkt eine PDF-Datei im A4-Format erstellen. Alles zusammen erledigt das folgende Kommando:

convert *.jpg -brightness-contrast 25x60 -page A4 ausgabe.pdf

In diesem Beispiel sind 25 und 60 die Parameter für Helligkeit (brightness) und Kontrast; je nach Qualität Ihrer eigenen Scans müssen Sie mit diesen Zahlen ein wenig experimentieren. Die Originalbilder werden nicht verändert, so dass Sie problemlos mehrere Anläufe nehmen können. Der Befehlsaufruf geht davon aus, dass im aktuellen Ordner (in den Sie in der Shell mit cd gewechselt sind) alle eingescannten Dateien liegen und diese die Dateiendung .jpg haben.

convert kann noch viel mehr, ein häufig genutztes Feature ist z. B. das Verkleinern von Bildern, um Thumbnails für eine Webseite zu erstellen oder hochaufgelöste Bilder vor dem Weiterleiten per Mail in eine akzeptable Dateigröße zu zwingen. Dazu dient die Option -resize:

convert original.jpg -resize 800x800 klein.jpg

erzeugt nicht etwa ein quadratisches Bild mit 800 x 800 Pixeln, sondern reduziert die Bildgröße so, dass Breite und Höhe maximal 800 Pixel haben. (Der zweite Wert in 800x800 ist die Höhe.) Listing 2 zeigt ein Beispiel dafür, wobei identify (ebenfalls aus dem ImageMagick-Paket) die Größe von Original und erzeugtem Bild anzeigt.

Listing 2

convert

Die Datei original.jpg hat die Auflösung 2492 x 3480 (Breite x Höhe), convert erzeugt daraus ein verkleinertes Bild mit der neuen Auflösung 573 x 800 – das Seitenverhältnis bleibt erhalten (ca. 1/1,40):

$ convert original.jpg -resize 800x800 kleiner.jpg
$ identify *.jpg
original.jpg JPEG 2492x3480 2492x3480+0+0 8-bit DirectClass 3.843MB 0.000u 0:00.000
kleiner.jpg JPEG 573x800 573x800+0+0 8-bit DirectClass 171KB 0.000u 0:00.000

Um Bildbearbeitungsaufgaben zu automatisieren, können Sie auch spezielle GUI-Tools verwenden, z. B. Phatch (Photo & Batch, Abbildung 4) [2,3], die Arbeit mit Shell-Tools hat aber den Vorteil, dass Sie sich daran gewöhnen, komplexe Shell-Kommandos zusammenzustellen, um Aufgaben schnell zu erledigen. Mehr Informationen zu convert finden Sie in einem älteren EasyLinux-Artikel [4].

Abbildung 4: Spezialisierte Anwendungen, wie die Foto-Batch-Verarbeitung Phatch, helfen auch beim Automatisieren eintöniger Aufgaben, sind aber auf den jeweiligen konkreten Zweck eingeschränkt.

Vorsicht bei der Automatisierung

So mächtig Shell-Befehle sind, so gefährlich können sie auch sein: Wenn Sie sich vertippen, entfesseln Sie schnell zerstörerische Kommandos und löschen beispielsweise ganze Verzeichnishierarchien. Darum sollten Sie einige Sicherheitsmechanismen einbauen. Bevor Sie eine Schleife oder Kommandos, die rekursiv arbeiten (d. h., die Dateien in allen Unterordnern anfassen), aufrufen, können Sie die möglichen Auswirkungen mit den folgenden beiden Tipps einschränken:

  1. Erstellen Sie zunächst vom Ordner, den Sie bearbeiten, eine Sicherheitskopie; im Home-Verzeichnis könnten Sie dazu etwa cp -a Dokumente Dokumente.bak eingeben, wenn Sie mit Dateien im Dokumente-Ordner arbeiten möchten.
  2. Setzen Sie vor potenziell riskante Befehle, die Sie in einer Schleife ausführen möchten, in einem ersten Test das Kommando echo, also z. B. echo mv ... statt mv ... – das führt dazu, dass die Shell die eigentlich gewünschten Befehle nicht ausführt, sondern nur (mit echo) in der Konsole ausgibt (Abbildung 5).

    Abbildung 5: Stellen Sie kritischen Kommandos ein "echo" voran, zeigt die Shell die Aktionen an, die sie ohne "echo" ausführen würde.

Diesen Artikel als PDF kaufen

Express-Kauf als PDF

Umfang: 5 Heftseiten

Preis € 0,99
(inkl. 19% MwSt.)

LinuxCommunity kaufen

Einzelne Ausgabe
 
Abonnements
 
TABLET & SMARTPHONE APPS
Bald erhältlich
Get it on Google Play

Deutschland

Ähnliche Artikel

  • Stromstoß für die Shell
    Shell-Skripte verrichten unter Linux allgegenwärtig ihren Dienst. Mit Bashdiff erhält die Standard-Shell Features, die Sie sonst nur in höheren Programmiersprachen finden.
  • Shell-Tipps
    Alte (Unix-) Hasen lieben sie, Linux-Ein- und Aufsteiger stehen ihr oft mindestens skeptisch bis ablehnend gegenüber: der Shell. Wie eine Muschelschale legt sie sich um die Perle (den Linux-Kernel) und regelt alle Kommunikation mit ihm. Dieses für viele unbekannte Wesen wollen wir in unserer neuen Reihe näher beleuchten und versuchen, Vorurteile abzubauen, sowie Ihnen einen Einblick in die Möglichkeiten dieser mächtigen Anwenderschnittstelle geben. fortgeschrittenere Shell-User seien an dieser Stelle aufgefordert, ihre Tipps und Tricks an uns zu schicken, so dass wir sie in dieser Serie weiter verbreiten können.
  • Mehr Komfort
    Von einfachen Abfragen bis hin zu komplexen Menüs: Mit dem Toolkit Dialog bauen Sie eine grafische Oberfläche für Shell-Skripte, die oft nicht mehr als eine zusätzliche Zeile brauchen.
  • Automatisiert in LibreOffice-Dokumenten suchen
    In einem Bestand von Hunderten von LibreOffice-Dokumenten finden Sie mit Odtgrep im Handumdrehen die gewünschte Datei.
  • Dr. Linux: Tricks auf der Kommandozeile
    Dass auf einer Kommandozeile Befehle eingegeben werden, ist normal. Aber mit der Linux-Standard-Shell Bash lassen sich auch Befehle anzeigen und verwalten, Ausgaben umleiten und Hilfe anfordern.
Kommentare

Infos zur Publikation

EL 11/2017-01/2018: Einstieg in Linux

Digitale Ausgabe: Preis € 9,80
(inkl. 19% MwSt.)

EasyLinux erscheint vierteljährlich und kostet 9,80 Euro. Weitere Infos zum Heft finden Sie auf der Homepage.

Das Jahresabo kostet ab 33,30 Euro. Details dazu finden Sie im Computec-Shop.

Bei Google Play finden Sie digitale Ausgaben für Tablet & Smartphone.

HINWEIS ZU PAYPAL: Die Zahlung ist ohne Paypal-Konto ganz einfach per Kreditkarte oder Lastschrift möglich!      

Stellenmarkt

Aktuelle Fragen

Lieber Linux oder Windows- Betriebssystem?
Sina Kaul, 13.10.2017 16:17, 3 Antworten
Hallo, bis jetzt hatte ich immer nur mit
IT-Kurse
Alice Trader, 26.09.2017 11:35, 2 Antworten
Hallo liebe Community, ich brauche Hilfe und bin sehr verzweifelt. Ih bin noch sehr neu in eure...
Backup mit KUP unter Suse 42.3
Horst Schwarz, 24.09.2017 13:16, 3 Antworten
Ich möchte auch wieder unter Suse 42.3 mit Kup meine Backup durchführen. Eine Installationsmöglic...
kein foto, etc. upload möglich, wo liegt mein fehler?
kerstin brums, 17.09.2017 22:08, 5 Antworten
moin, zum erstellen einer einfachen wordpress website kann ich keine fotos uploaden. vom rechne...
Arch Linux Netzwerkkonfigurationen
Franziska Schley, 15.09.2017 18:04, 0 Antworten
Moin liebe Linux community, ich habe momentan Probleme mit der Einstellung des Lan/Wlan in Arc...