向命令添加绝对路径选项

向命令添加绝对路径选项

给定一个 shell 命令(我们称之为“oldcommand”),是否有一个简单的 shell 脚本 newcommand.sh ,它的行为与 oldcommand 相同,只是它有一个新的“-location”选项,例如,

  newcommand -location path -nonfileoption1 x1 -fileoption2 x2 -fileoption3 x3  -nonfileoption4 x4

将执行

 oldcommand  -nonfileoption1 x1 -fileoption2 path/x2 -fileoption3 path/x3  -nonfileoption4 x4

答案1

如果您只关心开头的一个选项,那么这只是几行脚本。在任意位置解析选项并将其传递给oldcommand需要几行代码,并且需要了解哪些选项有值、哪些没有值。

为了简单的案件,

#!/bin/sh
[ "$#" -gt 2 && "x$1" = "x-location" ] && cd $2 && shift 2 && exec oldcommand "$@"
newcommand "$@"

对于复杂的情况,这听起来像是您可以做的事情getopt(不可移植)。进一步阅读:

根据与 OP 的讨论,这里是可用于简化问题的模式:以“`-fileopt”开头的选项应该在前面添加位置选项的值。所以(没有真正的错误检查,而不是真的处理路径名中嵌入的特殊字符):

#!/bin/sh
PREP=
if [ "$#" -gt 2 ]
then
    PREP="$2/"
    shift 2
    ARGS=
    while [ "$#" != 0 ]
    do
        case "x$1" in
        (x-fileopt*)
            ARGS="$ARGS $1 ${PREP}$2"
            shift 2
            ;;
        (*)
            ARGS="$ARGS $1"
            shift 1
        esac
    done
    oldcommand $ARGS
else
    oldcommand "$@"
fi

答案2

这闻起来很像XY问题。如果您想oldcommand将所有相对文件名视为相对于不同目录,请更改当前目录!

(cd path && oldcommand  -nonfileoption1 x1 -fileoption2 x2 -fileoption3 x3  -nonfileoption4 x4)

括号确保目录更改是本地的:下一个命令将在原始目录中执行。

如果你想将其打包到脚本中:

#!/bin/sh
cd "$1" && shift && "$@"

用法:

run-in path oldcommand  -nonfileoption1 x1 -fileoption2 x2 -fileoption3 x3  -nonfileoption4 x4

不过,对于命令行使用,临时目录更改可能更方便。它需要更多的输入,但它允许文件名完成开箱即用。 (您可以使包装脚本方法完成工作,但您需要为run-in脚本定义一个完成函数。)

cd path
oldcommand  -nonfileoption1 x1 -fileoption2 x2 -fileoption3 x3  -nonfileoption4 x4
cd -

或者

pushd path
oldcommand  -nonfileoption1 x1 -fileoption2 x2 -fileoption3 x3  -nonfileoption4 x4
popd

与您所要求的相比,这使得所有相对文件名都相对于path,不仅仅是在命令行上传递的文件名,还有oldcommand内部使用的任何相对文件名。这还假设它oldcommand本身不会更改为不同的目录。许多命令都满足这两个假设。

答案3

opt()
    case ${1##*:*}:${#2} in
    (--:*) ! x=$((x-2))  ;;
    (-nonfileoption:[!0]*) p=;;
    (-fileoption:[!0]*)    p=\$2/;;
    (*:0)  eval $"{$x"':?Bad option::arg: "$1::$2"}';;
    (*)    eval $"{$((x-1))"':?Bad option: "$1"}'
    esac

[ " -location" = " $1" ] && x=2 parm= &&
while  [ "$#" -ge "$((x+=2))" ]
do     eval 'opt  "${'"$((x-1))"'}" "${'"$x}\"" ||
          until [ "$x" -eq "$#" ] && break 2
          do    parm=$parm' "${'$((x+=1))}\"
          done
       parm=$parm' "${'$((x-1))'}"  "'$p\${$x}\"
done&& eval "set -- $parm"

相关内容