Home / EasyLinux / 2012 / 04 / Aufgaben mit der Shell automatisieren

Newsletter abonnieren

Lies uns auf...

Folge LinuxCommunity auf Twitter

Top-Beiträge

Heftarchiv

LinuxUser Heftarchiv

EasyLinux Heftarchiv

Ubuntu User Heftarchiv

Ubuntu User Heftarchiv

Partner-Links:

Das B2B Portal www.Linx.de informiert über Produkte und Dienstleistungen.

Vollautomatisch

Aufgaben mit der Shell automatisieren

07.10.2012 Die Shell erlaubt es Ihnen, Ihr Linux-System über Text-Kommandos zu steuern. Doch warum sollten Sie ein 70er-Jahre-Interface verwenden, wenn doch KDE und Gnome äußerst komfortabel sind und die Bedienung mit der Maus erlauben? Unter anderem wegen der Geschwindigkeit.

Betrachten Sie einmal die folgende Aufgabenstellung: Sie haben in den letzten Jahren eine Reihe von Dokumenten mit LibreOffice und anderen Programmen erstellt und dabei sauber eine Dateinamenskonvention der Form 2012-03-Brief-Finanzamt.odt verwendet. Der Ordner, der diese Dokumente enthält, ist nun aber sehr voll und unübersichtlich geworden – mehr Struktur muss her.

Sie planen, für jedes Jahr einen Ordner (2011, 2012 etc.) und darin jeweils zwölf Unterordner 01 bis 12 für die Monate anzulegen – die Dateien sollen dann in den passenden Ordner wandern und dabei die (danach nicht mehr nötigen) Jahres- und Monatsangaben in den Dateinamen verlieren. Aus der Datei 2012-03-Brief-Finanzamt.odt soll also die Datei Brief-Finanzamt.odt im Unterverzeichnis 03 des Ordners 2012 werden.

Das ist mit einem grafischen Dateimanager wie Dolphin zwar kein Problem: Für das Anlegen der Verzeichnisse wählen Sie im Kontextmenü mehrfach Neu erstellen / Ordner. Steht die neue Ordnerhierarchie, können Sie per Drag & Drop und zwei geöffneten Dolphin-Fenstern alle Dateien an die passende Stelle schieben. Zuletzt bleibt dann nur noch das Umbenennen der Dateien: Sie klicken jede einzeln mit der rechten Maustaste an, wählen aus dem Kontextmenü den Punkt Umbenennen und entfernen im Dateinamen Monat und Jahr (Abbildung 1).

Abbildung 1

Abbildung 1: Zahlreiche Dateien in Dolphin zu verschieben und ihnen neue Namen zu geben, ist eine langwierige Aufgabe.

Falls Sie das mit 300 Dateien machen müssen, die in zwei oder mehr Jahren durchaus zusammenkommen können, sind Sie eine Weile damit beschäftigt, und die Arbeit ist ein wenig nervtötend. Wenn Sie die Taste [F2] zum Umbenennen drücken und mit den Cursortasten von einer Datei zur nächsten springen, können Sie die Arbeit geringfügig beschleunigen – aber viel bringt das nicht.

Auftritt der Shell

Betrachten Sie dagegen die folgenden drei Shell-Kommandos, die Sie in ein über das Startmenü (oder über [Alt]+[F2] und Eingabe von konsole) geöffnetes Terminalfenster eingeben:

cd ~/Dokumente
mkdir -p {2009..2012}/{0{1..9},10,11,12}
for f in 2???-??-*; do mv "$f" "${f:0:4}/${f:5:2}/${f:8}"; done

Diese – zugegeben komplexen – drei Zeilen Text erledigen die Aufgabe automatisiert, ohne weitere Eingriffe. Doch was genau passiert hier?

  1. Das erste Kommando cd ~/Dokumente wechselt innerhalb der Shell in Ihren Dokumente-Ordner. Die Tilde ~ ist dabei eine Abkürzung für Ihr Home-Verzeichnis /home/Benutzername.
  2. Mit dem zweiten Kommando erzeugen Sie auf einen Schlag die gesamte benötigte Verzeichnishierarchie: mkdir steht für "make directory" (Verzeichnis erstellen), und die geschweiften Klammern helfen dabei, automatisch ganz viele Argumente für diesen Befehl zu erzeugen: {2009..2012} wird zu allen Zahlen zwischen 2009 und 2012, alternativ könnten Sie hier auch {2009,2010,2011,2012} schreiben, aber die Variante mit den beiden Punkten ist kürzer. Hinter dem Schrägstrich / folgt ein geschachtelter Ausdruck: Wenn Sie hier einfach {1..12} schreiben würden, ergäbe sich {1,2,3,4,5,6,7,8,9,10,11,12}, mit der Konstruktion 0{1..9} erzeugt die Shell die einstelligen Monatszahlen mit führender 0.

    Den gesamten Ausdruck interpretiert die Shell so, dass Sie alle möglichen Kombinationen der Form 2009/01, 2009/02, …, 2012/12 als Argumente für mkdir verwenden wollen; die Shell führt also tatsächlich das Kommando

    mkdir -p 2009/01 2009/02 2009/03 2009/04 2009/05 2009/06 2009/07 2009/08 2009/09 2009/10 2009/11 2009/12 2010/01 2010/02 2010/03 2010/04 2010/05 2010/06 2010/07 2010/08 2010/09 2010/10 2010/11 2010/12 2011/01 2011/02 2011/03 2011/04 2011/05 2011/06 2011/07 2011/08 2011/09 2011/10 2011/11 2011/12 2012/01 2012/02 2012/03 2012/04 2012/05 2012/06 2012/07 2012/08 2012/09 2012/10 2012/11 2012/12

    aus. Die Version mit geschweiften Klammern ist deutlich schneller zu tippen, und dieser Vorteil würde sich noch vergrößern, wenn Sie neben 2009 bis 2012 noch für weitere Jahre Ordner erzeugen wollten.

    mkdir hat hier noch die Option -p, die dafür sorgt, dass das Tool fehlende "Zwischenverzeichnisse" erzeugt. Versuchen Sie mal, in der Shell mkdir 2020/01 einzugeben: Sie erhalten dann die Fehlermeldung, dass der Ordner 2020 noch nicht existiert. Mit -p erzeugt mkdir dieses fehlende Verzeichnis automatisch, bevor es 2020/01 anlegt.

  3. Der größte Automatisierungsschritt folgt in der letzten Zeile. Es handelt sich bei dem langen Befehl um eine so genannte For-Schleife, die ein Kommando mehrfach ausführt. In diesem Fall sucht die Shell alle Dateien im aktuellen Ordner, die auf das Muster 2???-??-* passen. Das Fragezeichen steht dabei für ein beliebiges Zeichen, das Sternchen für beliebig viele davon. Das Muster erfasst also alle zuvor beschriebenen Dateinamen, z. B. 2012-03-Brief-Finanzamt.odt. Jeden dieser Dateinamen merkt sich die Shell nun für einen Schleifendurchlauf in der Variablen f (was am Code for f in ... liegt). Mit diesem Inhalt führt die Shell dann das Kommando mv "$f" "${f:0:4}/${f:5:2}/${f:8}" aus. Für den Beispieldateinamen 2012-03-Brief-Finanzamt.odt passiert dann Folgendes:
  4. $f ist einfach der Dateiname selbst, im Beispiel wieder 2012-03-Brief-Finanzamt.odt. Er ist das erste Argument für den mv-Befehl, der Dateien umbenennen und verschieben kann. Damit ist schon mal klar, welche Datei mv bearbeiten soll; es fehlt noch das zweite Argument, das hier aus drei Teilen zusammengesetzt wird, die durch Schrägstriche getrennt sind: Los geht es mit ${f:0:4}. Darüber sprechen Sie wieder den Dateinamen an, erhalten aber nur die ersten vier Zeichen – ab Position 0. Die Shell beginnt die Zählung bei 0; die Zeichen 0 bis 3 aus dem Dateinamen ergeben also 2012. Es folgt ein Schrägstrich und danach ${f:5:2} – das funktioniert genauso, liefert aber die Zeichen 5 und 6 (im Beispiel: 03) zurück. Nach einem weiteren Schrägstrich folgt abschließend ${f:8}. Hier fehlt die Längenangabe, was die Shell so interpretiert, dass Sie alle Zeichen ab Nummer 8 verwenden möchten. Für die Beispieldatei ergibt sich also insgesamt das Kommando

    mv "2012-03-Brief-Finanzamt.odt" "2012/03/Brief-Finanzamt.odt"

    Es verschiebt die Datei in den Ordner 2012/03/ und gibt ihr gleichzeitig den neuen Dateinamen Brief-Finanzamt.odt. Danach geht es mit der nächsten Datei weiter, bis alle Dateien am gewünschten Platz stehen.

Die Anführungszeichen um die beiden Argumente herum wären in diesem Fall nicht zwingend nötig gewesen; wenn Sie aber Leerzeichen in Ihren Dateinamen benutzen, müssen Sie mit diesen Zeichen arbeiten: Die Shell mag keine Leerzeichen in Argumenten. Um etwa (als einfachere Aufgabe) die Datei Name mit Blank.txt in Neuer Name.txt umzubenennen, müssten Sie das Kommando

mv "Name mit Blank.txt" "Neuer Name.txt"

verwenden, ohne die Anführungen sieht die Shell in dieser Zeile fünf Argumente (1. Name, 2. mit, 3. Blank.txt, 4. Neuer und 5. Name.txt) für das mv-Kommando und würde versuchen, vier Dateien (die ersten vier Argumente) in einen nicht vorhandenen Ordner namens Name.txt (das fünfte Argument) zu verschieben.

Komplexere Muster

Nun war das Aufgabenbeispiel für die Shell noch leicht gewählt, weil sich in den Beispieldateinamen schon alle Bestandteile (Jahr, Monat, Restname) an der richtigen Stelle befinden. Oft haben Sie es mit einer komplizierteren Situation zu tun. Die Lösung, die Sie hier finden, werden Sie eventuell nicht auf Anhieb verstehen – lassen Sie sich davon aber nicht irritieren, das Ziel der Darstellung ist, Sie von der Leistungsfähigkeit der Shell zu überzeugen. Die vorgestellten Befehle können Sie auch ohne vollständiges Verständnis verwenden und durch ein wenig Experimentieren Ihren eigenen Vorstellungen anpassen.

Etwas umständlicher wird das erste Beispiel etwa, wenn die Dateinamen anfangs die Form Brief-Finanzamt-17.3.2012-Kopie.odt haben: Das Datum steht mitten im Text und hat die Form Tag.Monat.Jahr, wobei Tag und Monat ein- oder zweistellig sein können.

Ein Muster, um solche Dateien in der For-Schleife zu bearbeiten, ist noch relativ schnell gefunden: Wenn Sie in der Shell

ls *-{[1-9],[0-3][0-9]}.{[1-9],[01][0-9]}.20??-*

eingeben, erscheinen alle Dateien mit passenden Namen. Komplizierter wird es, wenn Sie die einzelnen Bestandteile (Tag, Monat, Jahr) aus solchen Dateinamen herausziehen möchten: Das klappt nicht mehr mit demselben Trick wie oben, weil sich die Informationen nicht an einer fixen Stelle im Namen befinden. Stattdessen benötigen Sie so genannte reguläre Ausdrücke, mit denen es möglich ist, Teile eines Musters einzeln anzusprechen. Die folgenden Codezeilen funktionieren nur, wenn in der Shell-Variablen $NAME ein Dateiname gespeichert ist, der dem obigen Muster entspricht, also die Form Vorne-DD.MM.JJJJ-Hinten hat, wobei DD ein ein- oder zweistelliger Tag, MM ein ebenso ein- oder zweistelliger Monat und JJJJ ein vierstelliges Jahr (zwischen 2000 und 2099) ist. Das Muster ist so einfach wie möglich gehalten, passt also auch auf fehlerhafte Datumsangaben wie den 35.13.2012.

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
Tip a friend    Druckansicht Bookmark and Share
Kommentare

506 Hits
Wertung: 0 Punkte (0 Stimmen)

Schlecht Gut

Infos zur Publikation

Infos zur Publikation

title_2014_02

Aktuelle Ausgabe kaufen:

Heft als PDF kaufen

EasyLinux erscheint vierteljährlich und kostet EUR 9,80. Weitere Informationen zum Heft finden Sie auf der EasyLinux-Homepage.

Das EasyLinux-Jahresabo mit Prämie kostet ab EUR 33,30. Details zum EasyLinux-Jahresabo finden Sie im Medialinx-Shop.

Tipp der Woche

Bilder vergleichen mit diffimg
Bilder vergleichen mit diffimg
Tim Schürmann, 01.04.2014 12:40, 1 Kommentare

Das kleine Werkzeug diffimg kann zwei (scheinbar) identische Bilder miteinander vergleichen und die Unterschiede optisch hervorheben. Damit lassen sich nicht nur Rätsel a la „Orignial und Fäls...

Aktuelle Fragen

programm suche
Hans-Joachim Köpke, 13.04.2014 10:43, 8 Antworten
suche noch programme die zu windows gibt, die auch unter linux laufen bzw sich ähneln sozusagen a...
Funknetz (Web-Stick)
Hans-Joachim Köpke, 04.04.2014 07:31, 2 Antworten
Bei Windows7 brauche ich den Stick nur ins USB-Fach schieben dann erkennt Windows7 Automatisch, a...
Ubuntu 13.10 überschreibt immer Windows 8 Bootmanager
Thomas Weiss, 15.03.2014 19:20, 8 Antworten
Hallo Leute, ich hoffe das ich richtig bin. Ich habe einen Dell Insipron 660 Ich möchte gerne Ub...
USB-PTP-Class Kamera wird nicht erkannt (Windows-only)
Wimpy *, 14.03.2014 13:04, 15 Antworten
ich habe meiner Frau eine Digitalkamera, AGFA Optima 103, gekauft und wir sind sehr zufrieden dam...
Treiber
Michael Kristahn, 12.03.2014 08:28, 5 Antworten
Habe mir ein Scanner gebraucht gekauft von Canon CanoScan LiDE 70 kein Treiber wie bekomme ich de...