如何使用 *.sh 在不同目录中执行多个 .sh 文件

Moj*_*ian 3 linux bash shell-script

我需要编写一个 shell 脚本,.sh如果它们存在于目录模式中,它可以执行所有文件。就像是:

##!/bin/bash
sh /var/scripts/*/my_*.inc.sh
Run Code Online (Sandbox Code Playgroud)

但是上面的脚本只执行了一个文件;发生的第一个文件(似乎是由最新修改日期选择的),这不是我的观点。我需要执行与规则匹配的所有文件。

Kus*_*nda 8

您的代码不起作用的原因是文件名通配模式扩展时会发生什么。

该模式将扩展为匹配路径名的列表。脚本中的代码将sh使用此列表调用。这意味着它将执行第一个匹配的名称作为脚本,并将其他名称作为该脚本的参数

sh /var/scripts/dir/my_first.inc.sh /var/scripts/dir/my_second.inc.sh /var/scripts/dir/my_third.inc.sh
Run Code Online (Sandbox Code Playgroud)

相反,只需遍历匹配的名称:

sh /var/scripts/dir/my_first.inc.sh /var/scripts/dir/my_second.inc.sh /var/scripts/dir/my_third.inc.sh
Run Code Online (Sandbox Code Playgroud)

这假设每个匹配的名称都是一个应该由sh(not bash)执行的脚本。如果单个文件是可执行的并且具有正确的#!-line,sh则从上面循环中的脚本调用中删除。如果文件被“点脚本”,应源即脚本,然后更换sh.,而不是让脚本在当前脚本的环境中执行。

请注意,上面的脚本可以是sh脚本 ( #!/bin/sh),因为它不使用任何bash功能。如果其他脚本是“点脚本”,那么您显然必须将其更改为#!/bin/bash或需要其他任何解释器来获取脚本。


Sté*_*las 5

一个.inc.sh扩展建议.inc.sh应该包含这些文件,或者换句话说,它们的内容应该被一个shell 解释器评估为 shell 代码,这样同一个 shell 解释器可以执行一些其他代码,函数变量别名...定义在那些可用的文件中。

bash的语法大多与sh语法向后兼容,特别是当它的 POSIX 模式被启用时(当调用为时bash实际上是一个sh解释器sh),所以即使这些函数可能是用sh语言编写的,你仍然应该能够让bash解释器解释它们.

bash(当不在 POSIX 模式下)和之间的一个显着区别shbash不能alias在脚本中进行扩展。这可以通过设置expand_aliases选项或posix选项来解决,因此您可以执行以下操作:

#! /bin/bash -
set -o posix # increase POSIX sh compatibility, some but not all bash-specific
             # extensions are still available.

for file in /var/scripts/*/my_*.inc.sh; do
  . "$file"
done

# rest of the code that uses the functions/variables, etc defined
# in the files sourced above with the "." special builtin
Run Code Online (Sandbox Code Playgroud)

请注意,如果没有匹配的文件,则.在尝试获取不存在的文件/var/scripts/*/my_*.inc.sh并退出 shell时,该命令将失败。

如果在这种情况下你不想做任何你可以做的事情:

shopt -s nullglob
files=(/var/scripts/*/my_*.inc.sh)
shopt -u nullglob

for file in "${files[@]}"; do
  command . "$file"
done
Run Code Online (Sandbox Code Playgroud)

使用nullglob,没有匹配项的 glob 扩展到空列表而不是未扩展的模式。使用command前缀,特殊内置函数的失败.(例如 when$file不可读)不会导致 shell 退出(并且仍应报告错误)。

.inc.sh递归查找文件而不仅仅是 的子目录/var/scripts,您可以使用该globstar选项来启用**运算符:

shopt -s nullglob globstar
files=(/var/scripts/**/my_*.inc.sh)
shopt -u nullglob globstar
Run Code Online (Sandbox Code Playgroud)

在任何情况下,名称以.(隐藏的)开头的目录和文件都将被省略。dotglob如果要包括,请使用该选项,

显然,如果任何源脚本调用exitexec有语法错误或任何调用的特殊内置函数失败,也将退出脚本。