ソースlib / *が機能しないのはなぜですか?


11

次のフォルダー構造を含む小さなプログラムがあります。

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

各ファイルには、で使用する1つの関数が含まれていますmain.sh

main.sh

source lib/*

get_products
clean_products
make_index
test_index

上記では、最初の2つの関数は機能しますが、2番目の2つは機能しません。

それでも私source lib/*が次のように置き換えた場合:

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

すべてが期待どおりに機能します。

誰もがなぜsource lib/*期待どおりに機能しないのか知っていますか?


2
質問に答えずに、ワンライナーでやりたい場合/etc/bashrcは、forループを使用してを処理する方法を見てください/etc/profile.d/*.sh。その内容を信頼lib/できる場合は、1行に減らすことができますfor i in lib/*.sh; do . "$i"; done
リッチ

回答:


21

Bashのsourceビルトインは単一のファイル名のみを受け取ります:

source filename [arguments]

最初のパラメータを超えるものは、の位置パラメータになりますfilename

簡単なイラスト:

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

の完全な出力 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.

(これは、組み込みの同等の「ドットソース」にも適用され.ます。これは、注目に値しますが、POSIXの方法であるため、移植性が高くなります。)

一見矛盾する動作については、実行後にmain.shを実行してみてくださいset -x。どのステートメントが実行されているか、およびいつ手がかりが得られるかを確認します。


7

Bashのドキュメントは、それsourceが単一のファイル名で機能することを示しています

。(期間)

ファイル名 [引数]

現在のシェルコンテキストのfilename引数からコマンドを読み取り、実行します。ファイル名の場合...

そしてソースコード... for source ...はこれを裏付けています:

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

で呼び出すためにsource_file定義されevalfile.cている場所_evalfile

rval = _evalfile (filename, flags);

そして_evalfile、単一のファイルのみを開きます:

fd = open (filename, O_RDONLY);

5

bレイヤーの便利な回答を補完するものとして、拡張しようとしているタイプのファイルがそこにあるかどうか不明な場合は、貪欲なグロブ拡張を使用しないことをお勧めします。

以下に行ったとき、実行される可能性のある.shいくつかの有害なコマンド(例:)を含む一時ファイル(拡張子が付いていない)の可能性があります(rm -rf *実行権限がある場合)

source lib/*

したがって、あなただけの場合、*.shファイルだけでループすることができますが、常に適切なバインドされたセットでグロブ拡張を行ってください

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

ここでは[ -f "$globFile" ] || continue、現在のフォルダーに一致するグロブパターンがない場合、つまりシェルの拡張シェルオプションnullglobに相当する場合に、ループから戻る処理を行いますbash


プロセス置換を使用してcatも動作します:source <(cat lib/*.sh)
Xophmeister

@Xophmeister、「仕事」のより限定された値の場合。あなたが持つデバッグしようとした場合set -xPS4プットことBASH_SOURCELINENO、あなたのログに、あなたは、もはや与えられたコマンドがから来ているファイルと行を参照することができませんでした。
Charles Duffy

2
@Xophmeister、...また、スクリプトはを使用してその実行を短絡させることができreturnます。その慣習に従って、それを実行するスクリプトはすべて、後続のすべてのスクリプトの実行を妨げます
Charles Duffy

1
これは/etc/bashrc、を処理するときの方法にかなり近いです/etc/profile.d/*.sh
リッチ

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.