Mam mały program, który zawiera następującą strukturę folderów:
- main.sh
- lib/
- clean.sh
- get.sh
- index.sh
- test.sh
Każdy plik zawiera jedną funkcję, z której korzystam main.sh
.
main.sh
:
source lib/*
get_products
clean_products
make_index
test_index
Powyżej dwie pierwsze funkcje działają, ale dwie pozostałe nie.
Jednak jeśli zastąpię source lib/*
:
source lib/get.sh
source lib/clean.sh
source lib/index.sh
source lib/test.sh
Wszystko działa zgodnie z oczekiwaniami.
Czy ktoś wie, dlaczego source lib/*
nie działa zgodnie z oczekiwaniami?
/etc/bashrc
jak używafor
pętli do radzenia sobie/etc/profile.d/*.sh
. Jeśli ufasz, zawartośćlib/
można sprowadzić do jednej linijki:for i in lib/*.sh; do . "$i"; done
Odpowiedzi:
Wbudowane oprogramowanie Bash
source
zajmuje tylko jedną nazwę pliku:Wszystko poza pierwszym parametrem staje się parametrem pozycyjnym dla
filename
.Prosta ilustracja:
Pełna wydajność
help source
(Dotyczy to również wbudowanego równoważnego „źródła kropek”,
.
które, warto zauważyć, jest sposobem POSIX, a zatem bardziej przenośnym.)Jeśli chodzi o pozornie sprzecznych zachowań widzisz można spróbować uruchomić main.sh po zrobieniu
set -x
. Sprawdzanie, jakie instrukcje są wykonywane i kiedy może dostarczyć wskazówek.źródło
Dokumentacja Bash wskazuje, że
source
działa na jednej nazwie pliku :A kod źródłowy ... dla źródła ... tworzy kopię zapasową:
Gdzie
source_file
jest zdefiniowane,evalfile.c
aby zadzwonić_evalfile
:i
_evalfile
otwiera tylko jeden plik:źródło
Uzupełniając użyteczną odpowiedź warstwy b , sugerowałbym nigdy nie używać chciwego rozszerzenia glob, jeśli nie jesteś pewien, czy istnieją pliki typu, które próbują się rozwinąć.
Kiedy zrobiłeś poniżej, istnieje możliwość, że plik (bez
.sh
rozszerzenia) to tylko plik tymczasowy zawierający szkodliwe polecenia (np.rm -rf *
), Które można wykonać (zakładając, że mają uprawnienia do wykonywania)Dlatego zawsze wykonuj ekspansję glob z odpowiednim ustawionym zestawem, w twoim przypadku możesz po prostu zapętlić
*.sh
same plikiW tym przypadku
[ -f "$globFile" ] || continue
zadbałby o powrót z pętli, jeśli w bieżącym folderze nie pasuje żaden wzorzec globalny, tj. Odpowiednik opcji rozszerzonej powłokinullglob
wbash
powłoce.źródło
cat
również działałoby:source <(cat lib/*.sh)
set -x
a,PS4
który umieszczaBASH_SOURCE
iLINENO
w twoich logach, nie możesz już zobaczyć, z którego pliku i linii pochodzi dana komenda.return
. Zgodnie z tą praktyką każde wykonanie skryptu uniemożliwiłoby wykonanie wszystkich kolejnych./etc/bashrc
podczas przetwarzania/etc/profile.d/*.sh
.source
wymaga tylko uprawnień do odczytu, a nie wykonywania