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


11

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

- 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/*不按预期工作吗?


2
如果您想单行处理,请不要回答这个问题,请看/etc/bashrc一下它如何使用for循环来处理/etc/profile.d/*.sh。如果您相信lib/它的内容可以简化为一种:for i in lib/*.sh; do . "$i"; done
Rich

Answers:


21

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。查看正在执行的语句以及何时执行可以提供线索。


7

Bash文档指出source可以在单个文件名上运行

。(一段时间)

文件名 [参数]

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

而源代码的 ......这个备份起来:

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

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

rval = _evalfile (filename, flags);

并且_evalfile只打开一个文件:

fd = open (filename, O_RDONLY);

5

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

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

source lib/*

因此,请始终使用适当的绑定集进行全局扩展,尽管您可以只循环处理*.sh文件

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

在这里,[ -f "$globFile" ] || continue如果没有glob模式在当前文件夹中,即等同的扩展壳选择匹配会照顾的返回圈外nullglobbash外壳。


使用进行流程替换cat也可以:source <(cat lib/*.sh)
Xophmeister

@ Xophmeister,……对于“工作”的价值更为有限。如果您尝试使用set -x和在日志PS4中放入BASH_SOURCEand 进行调试LINENO,则您将无法再看到给定命令来自哪个文件和行。
查尔斯·达菲

2
@Xophmeister,...此外,脚本可以使用来缩短其执行return。按照这种做法,任何执行此操作的脚本都将阻止随后的所有脚本执行。
Charles Duffy

1
这与/etc/bashrc处理时的完成方式非常接近/etc/profile.d/*.sh
丰富

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.