Saya memiliki program kecil yang berisi struktur folder berikut:
- main.sh
- lib/
- clean.sh
- get.sh
- index.sh
- test.sh
Setiap file berisi satu fungsi yang saya gunakan di main.sh
.
main.sh
:
source lib/*
get_products
clean_products
make_index
test_index
Di atas dua fungsi pertama bekerja tetapi yang kedua tidak.
Namun jika saya ganti source lib/*
dengan:
source lib/get.sh
source lib/clean.sh
source lib/index.sh
source lib/test.sh
Semuanya berfungsi seperti yang diharapkan.
Adakah yang tahu mengapa source lib/*
tidak bekerja seperti yang diharapkan?
/etc/bashrc
bagaimana menggunakanfor
loop untuk menangani/etc/profile.d/*.sh
. Jika Anda memercayai isinyalib/
dapat direduksi menjadi satu-liner:for i in lib/*.sh; do . "$i"; done
Jawaban:
Bash's
source
builtin hanya membutuhkan satu nama file:Apa pun di luar parameter pertama menjadi parameter posisi
filename
.Ilustrasi sederhana:
Output penuh dari
help source
(Ini juga berlaku untuk built-in "dot source"
.
yang sepadan, yang patut dicatat, adalah cara POSIX dan karenanya lebih portabel.)Adapun perilaku yang tampaknya kontradiktif yang Anda lihat, Anda dapat mencoba menjalankan main.sh setelah melakukannya
set -x
. Melihat pernyataan apa yang dieksekusi dan kapan dapat memberikan petunjuk.sumber
Dokumentasi Bash menunjukkan bahwa
source
berfungsi pada satu nama file :Dan kode sumber ... untuk sumber ... mencadangkan ini:
Di mana
source_file
didefinisikanevalfile.c
untuk memanggil_evalfile
:dan
_evalfile
hanya membuka satu file:sumber
Melengkapi jawaban berguna b-layer , saya sarankan untuk tidak menggunakan ekspansi global yang rakus jika Anda tidak yakin apakah file-file dari tipe yang mencoba untuk memperluas ada di sana.
Ketika Anda melakukannya di bawah ini ada kemungkinan file (tidak memiliki
.sh
ekstensi) hanya file sementara yang berisi beberapa perintah berbahaya (misalnyarm -rf *
) yang dapat dieksekusi (dengan asumsi mereka memiliki izin yang dijalankan)Jadi selalu lakukan ekspansi glob dengan set terikat yang tepat, dalam kasus Anda meskipun Anda hanya bisa mengulang pada
*.sh
file sajaDi sini
[ -f "$globFile" ] || continue
akan menangani kembalinya keluar dari loop jika tidak ada pola bola cocok di folder saat ini yaitu setara dengan opsi shell diperpanjangnullglob
dibash
shell.sumber
cat
juga akan berfungsi:source <(cat lib/*.sh)
set -x
danPS4
yang menempatkanBASH_SOURCE
danLINENO
di log Anda, Anda tidak bisa lagi melihat file dan baris yang berasal dari perintah yang diberikan.return
. Mengikuti praktik itu, skrip apa pun yang melakukan itu akan mencegah semua yang mengikuti menjalankan./etc/bashrc
ketika diproses/etc/profile.d/*.sh
.source
hanya memerlukan izin baca, bukan eksekusi