459 Stimmen

Wie lassen sich andere Skripte am besten einbinden?

Normalerweise würde man ein Skript mit "source" einbinden

z. B:

main.sh:

#!/bin/bash

source incl.sh

echo "The main script"

incl.sh:

echo "The included script"

Die Ausgabe der Ausführung von "./main.sh" ist:

The included script
The main script

... Wenn Sie nun versuchen, das Shell-Skript von einem anderen Ort aus auszuführen, kann es das Include nicht finden, es sei denn, es befindet sich in Ihrem Pfad.

Wie kann man sicherstellen, dass das Skript das Include-Skript findet, insbesondere wenn das Skript beispielsweise portabel sein muss?

26voto

Brian Cannard Punkte 816

Eine Kombination der Antworten auf diese Frage bietet die solideste Lösung.

Es funktionierte für uns in produktionsreifen Skripten mit großartiger Unterstützung von Abhängigkeiten und Verzeichnisstrukturen:

#!/bin/bash

# Full path of the current script
THIS=\`readlink -f "${BASH\_SOURCE\[0\]}" 2>/dev/null||echo $0\`

# The directory where current script resides
DIR=\`dirname "${THIS}"\`

# 'Dot' means 'source', i.e. 'include':
. "$DIR/compile.sh"

Die Methode unterstützt alle diese Punkte:

  • Räume auf dem Weg
  • Links (über readlink )
  • ${BASH_SOURCE[0]} ist robuster als $0

23voto

Max Arnold Punkte 417
SRC=$(cd $(dirname "$0"); pwd)
source "${SRC}/incl.sh"

19voto

Alexar Punkte 1778

1. Das Schönste

Ich habe fast alle Vorschläge ausprobiert, und hier ist der beste, der bei mir funktioniert hat:

script_root=$(dirname $(readlink -f $0))

Es funktioniert auch, wenn das Skript mit einem Symlink zu einem $PATH Verzeichnis.

Sehen Sie es hier in Aktion: https://github.com/pendashteh/hcagent/blob/master/bin/hcagent

2. Das Coolste

# Copyright https://stackoverflow.com/a/13222994/257479
script_root=$(ls -l /proc/$$/fd | grep "255 ->" | sed -e 's/^.\+-> //')

Das stammt eigentlich aus einer anderen Antwort auf dieser Seite, aber ich füge es auch meiner Antwort hinzu!

3. Die zuverlässigste

Für den seltenen Fall, dass diese Methoden nicht funktionieren, gibt es eine andere, absolut sichere Methode:

# Copyright http://stackoverflow.com/a/7400673/257479
myreadlink() { [ ! -h "$1" ] && echo "$1" || (local link="$(expr "$(command ls -ld -- "$1")" : '.*-> \(.*\)$')"; cd $(dirname $1); myreadlink "$link" | sed "s|^\([^/].*\)\$|$(dirname $1)/\1|"); }
whereis() { echo $1 | sed "s|^\([^/].*/.*\)|$(pwd)/\1|;s|^\([^/]*\)$|$(which -- $1)|;s|^$|$1|"; } 
whereis_realpath() { local SCRIPT_PATH=$(whereis $1); myreadlink ${SCRIPT_PATH} | sed "s|^\([^/].*\)\$|$(dirname ${SCRIPT_PATH})/\1|"; } 

script_root=$(dirname $(whereis_realpath "$0"))

Sie können es in Aktion sehen in taskrunner Quelle: https://github.com/pendashteh/taskrunner/blob/master/bin/taskrunner

Hoffentlich hilft das jemandem da draußen :)

Hinterlassen Sie bitte auch einen Kommentar, wenn es bei Ihnen nicht funktioniert hat, und nennen Sie Ihr Betriebssystem und Ihren Emulator. Danke!

16voto

Alessandro Pezzato Punkte 8195

Dies funktioniert auch, wenn das Skript aus einer Quelle stammt:

source "$( dirname "${BASH_SOURCE[0]}" )/incl.sh"

9voto

Steve Baker Punkte 4217

Sie müssen den Speicherort der anderen Skripte angeben, es gibt keine andere Möglichkeit, dies zu umgehen. Ich würde eine konfigurierbare Variable am Anfang Ihres Skripts empfehlen:

#!/bin/bash
installpath=/where/your/scripts/are

. $installpath/incl.sh

echo "The main script"

Alternativ können Sie darauf bestehen, dass der Benutzer eine Umgebungsvariable pflegt, die angibt, wo sich Ihr Programm befindet, z. B. PROG_HOME oder ähnliches. Dies kann dem Benutzer automatisch zur Verfügung gestellt werden, indem ein Skript mit diesen Informationen in /etc/profile.d/ erstellt wird, das bei jeder Benutzeranmeldung aufgerufen wird.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X