我有一个包含以下文件夹结构的小程序:
- 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
. 查看正在执行哪些语句以及何时执行可能会提供线索。
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)
补充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
。