shell - 按层次结构创建 shell 子命令

标签 shell

我正在尝试为我的脚本创建一个系统 -
每个脚本都位于一个文件夹中,该文件夹就是命令本身。
脚本本身将充当子命令。

例如,名为“git”的目录中名为“who”的脚本,
将允许我在命令行中使用 git who 运行脚本。
另外,我想为伪命令创建一个子命令,这意味着当前不可用的命令。例如。 some-任意命令子命令。

这有可能吗?
我想到以某种方式扩展 https://github.com/basecamp/sub完成任务。

编辑1

#!/usr/bin/env bash

command=`basename $0`
subcommand="$1"
case "$subcommand" in
"" | "-h" | "--help" )
  echo "$command: Some description here" >&2
  ;;
* )
  subcommand_path="$(command -v "$command-$subcommand" || true)"
  if [[ -x "$subcommand_path" ]]; then
    shift
    exec "$subcommand_path" "${@}"
    return $?
  else
    echo "$command: no such command \`$subcommand'" >&2
    exit 1
  fi
  ;;
esac

这是我当前为新的自定义命令运行的脚本。
由于它太通用了,我只是复制粘贴它。
但我还是想知道 -
它是否足够通用,可以识别文件夹名称并通过其文件夹名称创建脚本?

但有一个问题是,如果它应该替换默认命令名称(例如 git),它似乎不会覆盖默认命令名称。

编辑2

经过一番修改之后,这就是我最终得到的结果:

#!/usr/bin/env bash

COMMAND=`basename $0`
SUBCOMMAND="$1"
COMMAND_DIR="$HOME/.zsh/scripts/$COMMAND"

case "$SUBCOMMAND" in
  "" | "-h" | "--help" )
    cat "$COMMAND_DIR/help.txt" 2>/dev/null ||
    command $COMMAND "${@}"
    ;;
  * )
    SUBCOMMAND_path="$(command -v "$COMMAND-$SUBCOMMAND" || true)"
    if [[ -x "$SUBCOMMAND_path" ]]; then
      shift
      exec "$SUBCOMMAND_path" "${@}"
    else
      command $COMMAND "${@}"
    fi
    ;;
esac

这是一个名为“helper-sub”的通用脚本,我符号链接(symbolic link)到我拥有的所有脚本目录(例如 ln -s $HOME/bin/helper-sub $HOME/bin/ssh)。

在我的 zshrc 中,我创建了这个来调用所有脚本:

#!/usr/bin/env bash

PATH=${PATH}:$(find $HOME/.zsh/scripts -type d | tr '\n' ':' | sed 's/:$//')
export PATH
typeset -U path

for aliasPath in `find $HOME/.zsh/scripts -type d`; do
  aliasName=`echo $aliasPath | awk -F/ '{print $NF}'`
  alias ${aliasName}=${aliasPath}/${aliasName}
done
unset aliasPath

示例可以在这里查看:https://github.com/iwfmp/zsh/tree/master/scripts

最佳答案

您无法将目录作为脚本执行,但您可以创建一个调用目录中脚本的包装器。

您可以使用函数(在您的配置文件脚本中或 FPATH 中的文件中)或包装脚本来执行此操作。

一个简单的函数可能如下所示:

git() {
    local subPath='/path/to/your/git'
    local sub="${1}" ; shift

    if [[ -x "${subPath}/${1}" ]]; then
        "${subPath}/${sub}" "${@}"
        return $?
    else
        printf '%s\n' "git: Unknown sub-command '${sub}'." >&2
        return 1
    fi
}

(这与您链接的sub项目的工作方式相同,只是简化了。)

当然,如果您确实想专门为 git 创建一个子命令(这不仅仅是一个示例),您需要确保内置的 git 命令仍然有效。在这种情况下,你可以这样做:

git() {
    local subPath='/path/to/your/git'
    local sub="${1}"

    if [[ -x "${subPath}/${sub}" ]]; then
        shift
        "${subPath}/${sub}" "${@}"
        return $?
    else
        command git "${@}"
        return 1
    fi
}

但可能值得指出的是,在这种情况下,git 支持通过 git config 添加任意别名:

git config --global alias.who '!/path/to/your/git/who'

关于shell - 按层次结构创建 shell 子命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23683860/

相关文章:

bash - 使用 AWS CLI 选择实例内的 Autoscaling 组标签

linux - bash 中的 mysql 带变量

shell - 减去相应的行

bash - 函数中的源文件采用函数参数

bash - grepping 顶部输出时出现未知符号条目

c# - 使用 C# 捕获 nslookup shell 输出

linux - 如何计算shell中不同列之间的值

python - 如何将错误消息从 shell 脚本传递到 Python 脚本?

bash - Makefile 中的脚本通常用于查找工具链的路径

git - 什么环境变量设置 Git Color.UI?