按层次结构创建shell子命令

时间:2014-05-15 16:27:09

标签: shell

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

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

这有可能吗?
我想到了以某种方式扩展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”的通用脚本我对所有脚本目录的符号链接(例如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

1 个答案:

答案 0 :(得分:1)

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

您可以使用函数(在配置文件脚本中或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'