Scriptverzeichnis finden

19. Dezember 2012 at 21:16

Verzeichnis-IconIch bastel oft kleine Scripte, die mir irgendwelche Aufgaben abnehmen und meist auch nicht lange leben. Oft arbeite ich bei solchen Helper-Scripts nicht so 100% sauber. Zum Beispiel erstelle ich häufig keine saubere temporäre Datei mit tmpfile, sondern benutze einfach ein File im aktuellen Verzeichnis. Oder ich benötige eine Eingabedatei für das Script und benutze einfach „input.txt“ statt das File per Commandline zu übergeben.

Dabei fiel ich schon einige Male darauf herein, dass solche Scripte oft nicht richtig funktionieren, wenn man sich beim Starten nicht im Verzeichnis des Scripts befindet. Wenn man das Script z.B. unter /usr/local/bin ablegt und es später vom Home-Verzeichnis (~) aus starten (mit /usr/local/bin/script.sh), wird er die Datei „input.txt“ natürlich im Home-Verzeichnis suchen und nicht dort, wo ich sie abgelegt habe.

Ein einfacher Trick, dies global zu lösen: Gleich am Anfang des Scripts mit cd in das Verzeichnis wechseln, in dem das Script liegt. Aber wie findet das Script heraus, wo es liegt?

Die Variable $0 enthält den Scriptnamen, wie er auf der Kommandozeile aufgerufen wurde. Starten wir das Script mit /usr/local/bin/script.sh enthält $0 den String „/usr/local/bin/script.sh“. Sind wir schon im richtigen Verzeichnis, würden wir es mit ./script.sh starten. So enthält $0 auch nur „./script.sh“.

Das Kommando dirname hilft uns weiter. Während basename den Dateinamen aus einem vollständigen Pfad löst, holt dirname nur den Pfad heraus:

# basename /usr/local/bin/script.sh
script.sh
# dirname /usr/local/bin/script.sh
/usr/local/bin
# basename ./script.sh
script.sh
# dirname ./script.sh
.

Nun hilft uns „.“ natürlich nicht sehr weiter, um das tatsächliche Verzeichnis herauszufinden. Aber das benötigen wir ja auch gar nicht, denn es genügt ja, den relativen Pfad zu erhalten, um mit cd dorthin zu wechseln. Und das funktionier auch mit dem aktuellen Verzeichnis „.“ ohne Probleme.

Nun starten wir unser Script wie folgt:

#!/usr/bin/env bash
cd $(dirname $0)

Das „dirname $0“ bringt das Verzeichnis zum Vorschein, so wie es auf der Kommandozeile eingegeben wurde (also absolut oder relativ zum aktuellen Verzeichnis) und mit cd wechseln wir dorthin. Somit wechselt das Script immer in das Verzeichnis, in dem es selbst liegt.

Klar, das ist nur, um die eigene Faulheit zu unterstützen, eine saubere Programmierung wäre natürlich eher zu empfehlen, aber mir half diese Zeile schon recht oft, so dass ich sie meist schon überall einsetze.