如何用Bash实现外部脚本自动添加到主脚本menu.sh中
需求
当用户将脚本放入tools文件夹时,自动将其添加到menu.sh的选项列表和执行逻辑中,无需手动修改menu.sh代码。
目录结构
~ └── scripts ├── menu.sh └── tools ├── pushing-code.sh ├── purge-data.sh └── run-scrape.sh
现有问题
当前menu.sh需要手动添加新脚本的配置:
- 在
options数组中添加脚本名称(如"run-scrape") - 在
case语句中添加对应的source执行行
现有menu.sh示例代码
title="title" prompt="Pick an option(number): " options=( "pushing code" \ "purge-data" \ "run-scrape" \ ) echo "$title" PS3="$prompt" select opt in "${options[@]}" "Quit"; do case "$REPLY" in 0) source $(pwd)/scripts/tools/pushing-code.sh; my_func;; 0) source $(pwd)/scripts/tools/purge-data.sh; my_func;; 0) source $(pwd)/scripts/tools/run-scrape.sh; my_func;; $((${#options[@]}+1))) echo "Goodbye!"; break;; *) echo "Invalid option. Try another one.";continue;; esac done
优化方案:动态生成菜单与执行逻辑
直接在menu.sh中动态读取tools文件夹的脚本,无需预定义选项和case分支。完整代码如下:
title="Script Menu" prompt="Pick an option(number): " # 定义tools目录路径(确保路径正确,这里假设menu.sh在scripts目录下) TOOLS_DIR="$(dirname "$0")/tools" # 动态读取tools目录下的.sh脚本,生成选项列表和脚本路径映射 options=() script_paths=() for script in "$TOOLS_DIR"/*.sh; do # 获取不带.sh后缀的脚本名作为选项显示 script_name=$(basename "$script" .sh) options+=("$script_name") script_paths+=("$script") done echo "$title" PS3="$prompt" select opt in "${options[@]}" "Quit"; do # 检查用户选择的是有效选项 if [[ "$REPLY" -ge 1 && "$REPLY" -le "${#options[@]}" ]]; then # 获取对应的脚本路径并执行 selected_script="${script_paths[$((REPLY-1))]}" source "$selected_script" # 假设每个脚本都定义了my_func函数,执行它 if command -v my_func &> /dev/null; then my_func else echo "Warning: my_func not found in $selected_script" fi elif [[ "$REPLY" -eq $(( ${#options[@]} + 1 )) ]]; then echo "Goodbye!" break else echo "Invalid option. Try another one." fi done
代码说明
- 动态读取脚本:通过
for script in "$TOOLS_DIR"/*.sh遍历tools目录下的所有shell脚本,避免手动维护选项列表。 - 选项与路径映射:用两个数组
options存显示名称,script_paths存对应脚本的绝对路径,确保执行时路径正确。 - 简化case逻辑:不再需要为每个脚本写单独的case分支,通过
REPLY数值直接索引到对应的脚本路径,自动执行。 - 兼容性处理:检查
my_func是否存在,避免脚本未定义函数时出错。
额外优化建议
- 如果希望选项显示更友好(比如把
pushing-code改成Pushing Code),可以在脚本里加注释或者单独的配置文件,不过动态读取脚本名已经能满足基础需求。 - 可以过滤掉非可执行的脚本,添加
if [[ -x "$script" ]]; then判断,只加入可执行的脚本。
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

