sourceコマンドは複数のスクリプトを読み込めない

f:id:rasukarusan:20200128173009p:plain:w500

結論

先に結論だけ言っておくとsource file1 file2はできない。file1, file2をsourceしたいなら下記のようにする。

find ~/local_scripts |while read script; do
    source $script
done

# もしくはfor文でもいい
for script $(find ~/local_scripts); do
    source $script
done

いずれにせよsourceコマンドは1つずつ実行する必要がある。
sourceコマンドの第二引数以降はスクリプトの引数($1$2)としてみなされてしまうからだ。
sourceコマンドのmanにもそう書いてある。というかsourceはただのコマンド実行だからそりゃそうだよねっていう。

source filename [arguments]

ここからポエム

.zshrcには載せたくないローカル用のスクリプトがある。
そんな時は.zshrc.localのようなスクリプトを用意して、そこにローカル用の関数を書いていくってこと結構あると思う。

.zshrc.local

#!/usr/bin/env bash

echo_local() {
    echo 'This is local'
}

上記のような.zshrc.localを用意したら.zshrcの末尾にsource ~/.zshrc.localと書けば、echo_local()がコマンドとして使えるようになる。

$ echo_local
This is local

が、関数が多くなるにつれてファイル分割したくなってくる。そんなときに罠にかかった話。

sourceコマンドで読み込めばいいじゃんと思うじゃん

例えば下記のように関数をファイル分割した場合

ディレクトリ構造

~/local_scripts
    |-- echo_local.sh
    `-- echo_local2.sh

echo_local.sh

#!/usr/bin/env bash

echo_local() {
    echo 'This is local'
}

echo_local2.sh

#!/usr/bin/env bash

echo_local2() {
    echo 'This is local 2'
}

.zshrcに下記を記載すればいけると思った。

source ~/local_scripts/*

が、これはできない。展開するとsource ~/echo_local.sh ~/echo_local2.shとなるからだ。

終わり

あとは最初の結論にも書いたとおり。
読み込みたいファイルが引数として解釈されてしまうから、1つずつsourceしましょうねって話。