Ich habe ein kleines Programm, das die folgende Ordnerstruktur enthält:
- main.sh
- lib/
- clean.sh
- get.sh
- index.sh
- test.sh
Jede Datei enthält eine einzelne Funktion, in der ich verwende main.sh
.
main.sh
::
source lib/*
get_products
clean_products
make_index
test_index
Oben funktionieren die ersten beiden Funktionen, die zweiten beiden jedoch nicht.
Wenn ich jedoch ersetze source lib/*
durch:
source lib/get.sh
source lib/clean.sh
source lib/index.sh
source lib/test.sh
Alles funktioniert wie erwartet.
Weiß jemand, warum source lib/*
nicht wie erwartet funktioniert?
/etc/bashrc
wie einefor
Schleife verwendet wird/etc/profile.d/*.sh
. Wenn Sie vertrauen, kann der Inhaltlib/
auf einenfor i in lib/*.sh; do . "$i"; done
Antworten:
Bashs
source
eingebauter Dateiname hat nur einen einzigen Dateinamen:Alles, was über den ersten Parameter hinausgeht, wird zu einem Positionsparameter für
filename
.Eine einfache Illustration:
Volle Ausgabe von
help source
(Dies gilt auch für die entsprechende eingebaute "Punktquelle",
.
die, wie erwähnenswert, auf POSIX-Weise und damit portabler ist.)Was das scheinbar widersprüchliche Verhalten betrifft, können Sie versuchen, main.sh nach dem Ausführen auszuführen
set -x
. Zu sehen, welche Anweisungen wann ausgeführt werden, kann einen Hinweis geben.quelle
Die Bash-Dokumentation gibt an, dass
source
ein einzelner Dateiname verwendet wird :Und der Quellcode ... für die Quelle ... sichert dies:
Wo
source_file
ist definiert inevalfile.c
um aufzurufen_evalfile
:und
_evalfile
öffnet nur eine einzige Datei:quelle
Ergänzen zur nützlichen Antwort von b-layer würde ich empfehlen, niemals eine gierige Glob-Erweiterung zu verwenden, wenn Sie sich nicht sicher sind, ob die Dateien des Typs, der erweitert werden soll, vorhanden sind.
Wenn Sie dies unten getan haben, besteht die Möglichkeit, dass eine Datei (ohne
.sh
Erweiterung) nur eine temporäre Datei enthält, die einige schädliche Befehle enthält (z. B.rm -rf *
), die ausgeführt werden könnten (vorausgesetzt, sie haben Ausführungsberechtigungen).Führen Sie die Glob-Erweiterung also immer mit dem richtigen gebundenen Satz durch, in Ihrem Fall, obwohl Sie nur
*.sh
Dateien alleine durchlaufen könntenHier
[ -f "$globFile" ] || continue
würde sich das um das Zurückkehren aus der Schleife kümmern, wenn im aktuellen Ordner kein Glob-Muster übereinstimmt, dh äquivalent zu den erweiterten Shell-Optionennullglob
in derbash
Shell.quelle
cat
würde auch funktionieren:source <(cat lib/*.sh)
set -x
undPS4
dass PutsBASH_SOURCE
undLINENO
in Ihren Protokollen, könnten Sie nicht mehr , die Datei sehen und ein gegebener Befehl herkommt auskleiden.return
. Nach dieser Vorgehensweise würde jedes Skript, das dies tut, die Ausführung aller folgenden Skripte verhindern ./etc/bashrc
bei der Verarbeitung gemacht wird/etc/profile.d/*.sh
.source
erfordert nur Leseberechtigungen, nicht ausführen