如何让BASH Script接受插件



我已经完成了一个BASH脚本,但是现在我需要为它添加接受插件的功能。

例如,该脚本可以将文件从一个文件系统位置移动到另一个文件系统位置。它目前编写利用mv命令为此,但我想知道如何给用户选择做两件事:
用其他东西替换mv命令,rsync例如
重新定义整个move"函数的改进版本

我在网上找到了一些方法,但我不确定这是正确的方法。

"将mv命令替换为其他命令"的想法:
提供一个规范文档,定义所有可以替换的命令(及其相关的开关)。我想它还应该说明这些调整可以在哪里/如何进行。

用改进版本重新定义整个move函数的想法";
创建一个插件文件,其中包含一个与用户要重新定义的函数同名的函数。我相信这将覆盖给定函数的默认代码。

我想知道"正确的方法"。在概念层面上实现插件功能,以及如何在BASH脚本中具体实现。

定义接口

最重要的部分不是关于实现,而是关于文档和用法。你所依赖的每一个小细节都必须与用户沟通。

mv可覆盖命令示例。使用惰性规范mv: Move "$1" to "$2",您的脚本可能会在以下情况下中断:

  • 您使用mv source1 source2 target/
  • 您使用mv -n source target来防止覆盖现有文件
  • 您假设mv在没有询问和错误的情况下覆盖现有目标。
  • 你假设mv不打印任何东西,例如在var=$(mv a /tmp/; ls; mv /tmp/a ./)
  • 假设mv sourcedir/ targetdir/mv sourcedir targetdir是相同的。提示:rsync的行为改变基于尾斜杠

当您仔细定义了标准化接口后,您可以考虑实现。

2。实现一个插件系统

2.1使用bash的默认行为(相当hacky)

从技术上讲,您不必在这里做任何事情,因为bash中的大多数命令已经是"插件",即$PATH变量中指定的可执行二进制文件或脚本文件。

如果用户想要编写自己的mv作为your_script.sh的插件,他们已经可以运行…

mkdir /tmp/script_plugins
echo '#! /usr/bin/env bash
echo This is the mv plugin of the user
mv "$@"
' > /tmp/script_plugins/mv
chmod u+x /tmp/script_plugins/mv
export PATH="/tmp/script_plugins:$PATH"
./your_script.sh

…除非your_script.sh再次覆盖PATH或定义函数mv或类似的东西。

2.2使用专用名称(cleaner)然而,为了更简洁,我会将插件定义为具有专用名称的函数,以强调这些函数可以被覆盖:

#! /usr/bin/env bash
# Content of your_script.sh
if declare -pf USER_PLUGIN_MV &> /dev/null; then
# user defined and exported a plugin function
plugable_mv() { "$USER_PLUGIN_MV" "$@"; }
else
# no plugin was specified, use default implementation
plugable_mv() { mv "$@"; }
fi
for i in "just" "an" "example"; do
plugable_mv "$i" target/
done

如果用户定义并导出一个名为USER_PLUGIN_MV的函数,则该函数将被用于而不是默认的mv命令。

USER_PLUGIN_MV() { echo "plugin received args: $*"; }
export -f USER_PLUGIN_MV
./your_script.sh

…打印…

plugin received args: just target/
plugin received args: an target/
plugin received args: example target/

2.3使用命令字符串或者,您可以让用户指定命令字符串(如xargsbash -c或GNUparallel中所见),例如. ...

./your_script.sh --replace-mv-with 'echo "plugin received args: $*"'

这些可以实现为…

# things starting with PSEUDO_ are pseudo code
if PSEUDO_user_specified_mv_plugin; then
plugable_mv() {
# either ...
bash -c "$PSEUDO_mv_plugin_arg" user_plugin_mv "$@"
# ... or if plugins have to access/define/alter your variables
eval "$mv_plugin_arg"
}
else
plugable_mv() { mv "$@"; }
fi

然而,嵌套引号一旦插件变大,就会给大多数用户带来严重的问题。所以,如果你实现了这个系统,我仍然建议你的用户使用导出函数…

USER_PLUGIN_MV() { echo "plugin received args: $*"; }
export -f USER_PLUGIN_MV
./your_script.sh --replace-mv-with 'USER_PLUGIN_MV "$@"'

相关内容

  • 没有找到相关文章

最新更新