给定一个 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"