シェルコマンド(「oldcommand」と呼びます)が与えられた場合、新しい「-location」オプションがあることを除いて、oldcommandと同じように動作する単純なシェルスクリプトnewcommand.shはありますか?
newcommand -location path -nonfileoption1 x1 -fileoption2 x2 -fileoption3 x3 -nonfileoption4 x4
実行されます
oldcommand -nonfileoption1 x1 -fileoption2 path/x2 -fileoption3 path/x3 -nonfileoption4 x4
答え1
最初に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"