С помощью выреза (закрепки на конце/
):
ORACLE_HOME=$(printf "%s" "$ORACLE_HOME" | cut -d/ -f1-3)/
Использование расширения параметра дважды; первый удаляет первые два элемента каталога, затем второй удаляет оставшиеся элементы исходной переменной:
suffix=${ORACLE_HOME#/*/*/}
ORACLE_HOME=${ORACLE_HOME%"$suffix"}
Это стало довольно распространенным способом предоставления инструмента, который может выполнять несколько действий в зависимости от того, какая «подкоманда» используется. Насколько я знаю, это не стандартизировано, и использование точки в качестве разделителя между именем базовой команды и подкомандой при их совместном написании определенно не является универсальным для этих инструментов.
Некоторые инструменты можно вызывать только с подкомандой, например,git
(git
сам по себе предоставляет текст справки, если он вызывается сам по себе ), но предоставляет руководства для подкоманд, таких какman command-subcommand
(как и в случае с подкомандами git
).
Очевидно, вы нашли инструмент, который может называться command-subcommand
(, но с точкой)или как command subcommand
. В этом случае,вы, вероятно, обнаружите, что и базовая команда, и каждая комбинированная команда являются либо символическими ссылками, либо жесткими ссылками на один и тот же файл.
Программа (, будь то скрипт или скомпилированный двоичный файл ), может легко проверить, под каким именем она была вызвана и с какими аргументами, и соответствующим образом настроить свои действия.
Ниже приведен пример вымышленной команды process
, которая может принимать подкоманду в качестве первого аргумента, как в process action
, или вызываться с помощью подкоманды, например process-action
.
Этот скрипт реализует следующие подкоманды compile
, debug
и mogrify
.
#!/bin/sh
basecmd=process # base command name
cmd=${0##*/} # get command name ( basename "$0" )
subcmd= # no sub command yet
# Now pick out the sub command from the command name,
# or from the first argument. Then fail if unsuccessful.
case $cmd in
"$basecmd"-*) # has sub command in command name
subcmd=${cmd#$basecmd-}
esac
if [ -z "$subcmd" ] && [ "$#" -ge 1 ]; then
# called as "process action"
# rather than as "process-action"
subcmd=$1
shift # remove sub command from argument list
fi
if [ -z "$subcmd" ]; then
echo 'No action' >&2
exit 1
fi
# Act on the sub command.
# Each action would probably be implemented as a function,
# possibly called as
# somefunction "$@"
#... passing the remaining command line argument to it.
case $subcmd in
compile) # do "compile" action
echo 'compile'
;;
debug) # do "debug" action
echo 'debug'
;;
mogrify) # do "mogrify action"
echo 'mogrify'
;;
*)
printf 'Invalid action "%s"\n' "$subcmd" >&2
exit 1
esac
Я написал это для POSIX sh
, так как нет ничего таинственного, что требовало бы bash
для того, чтобы это работало. Программа на языке C будет делать то же самое, что и программа, написанная на любом другом компилируемом или интерпретируемом языке. Это также не требует Linux; Я пишу и тестирую это на OpenBSD, и оно должно работать на любой системе POSIX.
Наряду с этим базовым process
сценарием будет набор жестких или символических ссылок, по одной для каждой подкоманды. Здесь я решил создать жесткие ссылки :
$ ls -li
total 8
244420 -rwxr-xr-x 4 kk wheel 538 May 9 21:55 process
244420 -rwxr-xr-x 4 kk wheel 538 May 9 21:55 process-compile
244420 -rwxr-xr-x 4 kk wheel 538 May 9 21:55 process-debug
244420 -rwxr-xr-x 4 kk wheel 538 May 9 21:55 process-mogrify
Каждое из этих имен — просто другое имя для одного и того же сценария.
Тест -работает:
$./process mogrify
mogrify
$./process-mogrify
mogrify
$./process
No action
$./process-compile
compile
$./process compile
compile
$./process compilee
Invalid action "compilee"