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

Phi*_*ide 11 bash source

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

- main.sh
- lib/
  - clean.sh
  - get.sh
  - index.sh
  - test.sh
Run Code Online (Sandbox Code Playgroud)

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

main.sh

source lib/*

get_products
clean_products
make_index
test_index
Run Code Online (Sandbox Code Playgroud)

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

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

source lib/get.sh
source lib/clean.sh
source lib/index.sh
source lib/test.sh
Run Code Online (Sandbox Code Playgroud)

一切都按预期工作。

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

B L*_*yer 21

Bash 的source内置函数只需要一个文件名:

source filename [arguments]
Run Code Online (Sandbox Code Playgroud)

超出第一个参数的任何内容都将成为 的位置参数filename

一个简单的说明:

$ cat myfile
echo "param1: $1"
$ source myfile foo
param1: foo
Run Code Online (Sandbox Code Playgroud)

全输出 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.
Run Code Online (Sandbox Code Playgroud)

(这也适用于等效的“点源”内置.,值得注意的是,它是 POSIX 方式,因此更便携。)

至于您看到的看似矛盾的行为,您可以尝试在执行set -x. 查看正在执行哪些语句以及何时执行可能会提供线索。


Jef*_*ler 7

Bash 文档表明source适用于单个文件名

. (一段时间)

. 文件名[参数]

从当前 shell 上下文中的filename参数读取和执行命令。如果文件名...

源代码............支持这一点:

result = source_file (filename, (list && list->next));
Run Code Online (Sandbox Code Playgroud)

在哪里source_file定义evalfile.c调用_evalfile

rval = _evalfile (filename, flags);
Run Code Online (Sandbox Code Playgroud)

并且_evalfile只打开一个文件:

fd = open (filename, O_RDONLY);
Run Code Online (Sandbox Code Playgroud)


Ini*_*ian 5

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

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

source lib/*
Run Code Online (Sandbox Code Playgroud)

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

for globFile in lib/*.sh; do
    [ -f "$globFile" ] || continue
    source "$globFile"
done
Run Code Online (Sandbox Code Playgroud)

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

  • @Xophmeister,...此外,脚本可以使用 `return` 短路其执行。按照这种做法,任何执行此操作的脚本都会阻止 *all* 后续脚本的执行。 (2认同)