我有一个小程序,其中包含以下文件夹结构:
- 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
将负责从循环中返回。nullglob
bash