为什么 source lib/* 不起作用?

为什么 source lib/* 不起作用?

我有一个小程序,其中包含以下文件夹结构:

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

每个文件都包含一个我在main.sh.

main.sh

source lib/*

get_products
clean_products
make_index
test_index

在上面的例子中,前两个函数起作用,但后两个函数不起作用。

但如果我替换source lib/*为:

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

一切都按预期进行。

有谁知道为什么source lib/*不能按预期工作?

答案1

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。查看哪些语句被执行以及何时被执行可能会提供线索。

答案2

bash 文档表示source适用于单个文件名

。 (一段时间)

文件名[论据]

读取并执行来自的命令文件名当前 shell 上下文中的参数。如果文件名...

以及源代码...来源...支持这一点:

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

source_file定义在哪里evalfile.c致电_evalfile

rval = _evalfile (filename, flags);

并且_evalfile只打开一个文件:

fd = open (filename, O_RDONLY);

答案3

互补b层有用的答案,如果您不确定尝试扩展的类型的文件是否存在,我建议永远不要使用贪婪的全局扩展。

当您执行以下操作时,可能会出现一个文件(没有.sh扩展名)只是一个临时文件,其中包含一些rm -rf *可能被执行的有害命令(例如)(假设它们具有执行权限)

source lib/*

因此,始终使用适当的绑定集进行全局扩展,在您的情况下,尽管您可以单独循环*.sh文件

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

如果当前文件夹中没有匹配的全局模式,即相当于shell中的扩展 shell 选项,则这里[ -f "$globFile" ] || continue将负责从循环中返回。nullglobbash

相关内容