如何将目录中的所有脚本包含到当前 shell 会话中?

如何将目录中的所有脚本包含到当前 shell 会话中?

我有一个包含一些脚本文件的目录:

/scripts
    api.sh
    time.sh
    certificate.sh
    docker.sh
    nginx.sh
    wifi.sh
    ...

这些脚本不是命令。它们只是包含一些功能。因此我无法添加/script$PATH运行它们。例如api.sh有这样的内容:

function isApi()
{
   # body
}

function resetApi()
{
   # body
}

function testDatabase()
{
   # body
}

我需要将它们包含在当前会话中,然后调用它们的函数。

如果我将它们一一包括在内,. /scripts/x.sh我就可以使用它们的功能。

但是当我运行loadScripts.shbash 脚本来加载它们时,它不起作用:

find /scripts -mindepth 1 |
while read scriptFile;
do
    echo $scriptFile
    source $scriptFile
done

如何在当前会话中包含目录的所有脚本?

答案1

只是:

for script in scripts/*.sh; do
  . "$script"
done

特殊.的 sh 内置命令告诉 shell 评估所提供文件中的代码。 csh 具有source类似的命令,某些 shell 支持bash这两种命令.source有时语义略有不同。

您还需要确保在 上使用./ 。这样做会启动一个新的 shell 来解释脚本,因此在该短暂的 shell 中定义这些函数,而不是在调用的 shell 中。sourceloadScripts.sh./loadScripts.sh

还要确保 a包含在传递给/ 的/路径中,例如通过在当前工作目录中运行 if ,否则其路径可能会在 中查找。.source. ./loadScripts.sh$PATH

这样做find... | while read...; do . ...; done是错误的,首先是因为上面提到的所有原因为什么循环查找的输出是不好的做法?,但也是因为在多个 shell 中,包括未启用bash该选项时,循环将在子 shell 中运行,因此源文件中的函数只会在该子 shell 中定义。lastpipewhile

如果您想使用4.4 或更高版本find,但要注意find不对文件列表进行排序并包含隐藏文件bash,您可以这样做:

while IFS= read -rd '' -u3 script; do
  . "$script"
done 3< <(LC_ALL=C find scripts/ -mindepth 1 -maxdepth 1 -name '*.sh' -type f -print0)

这里添加一个-type f(以限制类型的文件常规的)来证明使用的合理性find

如果使用zsh而不是bash,你可以这样做:

for script (scripts/*(ND.)) . $script

作为等效文件(.仅限于常规文件,并D包括隐藏文件)。

或者:

for script (scripts/*(ND.)) emulate sh -c '. $script'

如果这些脚本的sh语法如.sh扩展所建议的那样。


posix¹ 无论该选项是否启用,bash 在这方面的行为都会有所不同。

相关内容