Kaynak lib / * neden çalışmıyor?


11

Aşağıdaki klasör yapısını içeren küçük bir program var:

- main.sh
- lib/
  - clean.sh
  - get.sh
  - index.sh
  - test.sh

Her dosyada kullandığım tek bir işlev var main.sh.

main.sh:

source lib/*

get_products
clean_products
make_index
test_index

Yukarıda ilk iki işlev çalışır, ancak ikincisi çalışmaz.

Ancak ben yerine source lib/*:

source lib/get.sh
source lib/clean.sh
source lib/index.sh
source lib/test.sh

Her şey beklendiği gibi çalışıyor.

Neden source lib/*beklendiği gibi çalışmadığını bilen var mı?


2
Soruyu cevaplamamak, eğer tek satırda yapmak istiyorsanız , başa çıkmak /etc/bashrciçin nasıl bir fordöngü kullandığına bakın /etc/profile.d/*.sh. Eğer içeriğine güvenirseniz, lib/bir astar için azaltılabilir:for i in lib/*.sh; do . "$i"; done
Zengin

Yanıtlar:


21

Bash sourceyerleşkesi yalnızca tek bir dosya adı alır:

source filename [arguments]

İlk parametrenin ötesinde herhangi bir şey konumsal bir parametre haline gelir filename.

Basit bir örnek:

$ cat myfile
echo "param1: $1"
$ source myfile foo
param1: foo

Tam çıktı help source

source: source filename [arguments]

Execute commands from a file in the current shell.

Read and execute commands from FILENAME in the current shell.  The
entries in $PATH are used to find the directory containing FILENAME.
If any ARGUMENTS are supplied, they become the positional parameters
when FILENAME is executed.

Exit Status:
Returns the status of the last command executed in FILENAME; fails if
FILENAME cannot be read.

(Bu ., dikkat çekmeye değer, POSIX yolu ve dolayısıyla daha taşınabilir olan eşdeğer "nokta kaynağı" yerleşik için de geçerlidir .)

Gördüğünüz gibi çelişkili davranışlara gelince, yaptıktan sonra main.sh çalıştırmayı deneyebilirsiniz set -x. Hangi ifadelerin yürütüldüğünü ve ne zaman ipucu verebileceğini görmek.


7

Bash belgelerisource tek bir dosya adında çalıştığını gösterir :

. (nokta)

. dosyaadı [argümanlar]

Geçerli kabuk bağlamındaki dosya adı bağımsız değişkeninden komutları okuma ve yürütme . Eğer dosya adı ...

Ve kaynak kodu ... kaynak için ... bunu yedekler:

result = source_file (filename, (list && list->next));

Aramak için nerede source_filetanımlanır :evalfile.c_evalfile

rval = _evalfile (filename, flags);

ve _evalfileyalnızca tek bir dosya açar:

fd = open (filename, O_RDONLY);

5

B-katmanın yararlı cevabını tamamlayan , genişletmeye çalışan türdeki dosyaların orada olup olmadığından emin değilseniz, asla açgözlü bir glob genişletmesi kullanmanızı önermem.

Aşağıda yaptığınızda, bir dosya ( .shuzantı içermeyen), yalnızca çalıştırılabilecek bazı zararlı komutlar (örn. rm -rf *Yürütme izinlerine sahip olduklarını varsayarak) içeren geçici bir dosya olasılığı vardır.

source lib/*

Yani her zaman açık sizin durumda olsa yapabildin sadece döngü doğru ciltli set ile glob genişleme yapmak *.shyalnız dosyalar

for globFile in lib/*.sh; do
    [ -f "$globFile" ] || continue
    source "$globFile"
done

İşte [ -f "$globFile" ] || continuehiçbir gıdım bile desen genişletilmiş kabuk seçeneklerinin eşdeğer yani klasör akım eşleşirse dönen dışarı döngünün dikkat çekmek nullglobiçinde bashkabuk.


Süreç ikamesi ile kullanmak catda işe yarayacaktır:source <(cat lib/*.sh)
Xophmeister

@Xophmeister, ... "iş" için daha sınırlı bir değer için. Hata ayıklamaya çalıştıysanız set -xve PS4bu koyar BASH_SOURCEve LINENOgünlüklerinizde, artık verilen bir komutun hangi dosya ve satırdan geldiğini göremezsiniz.
Charles Duffy

2
@Xophmeister, ... ayrıca, bir senaryo yürütmeyi kısa devre yapabilir return. Bu uygulamanın ardından, bunu yaparken herhangi bir komut dosyası önleyecek tüm yürütülmesini aşağıdaki olanları.
Charles Duffy

1
Bu işlem /etc/bashrcyaparken nasıl yapıldığına oldukça yakın /etc/profile.d/*.sh.
Zengin

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.