for i in `echo $PATH | sed 's/^:/.:/
s/::/:.:/g
s/:$/:./
s/:/ /g'`
do
if test -f $i/$1 # use test -x if you can
then
echo $i/$1
exit 0 # found it
fi
done
exit 1 # not found
$
Проверим ее:
$ cx which
$ which which
./which
$ which ed
/bin/ed
$ mv which /usr/you/bin
$ which which
/usr/you/bin/which
$
Первый оператор case
1>&2 в команде echo, которое выполняется для того, чтобы сообщение об ошибке не пропало в программном канале. Встроенная команда интерпретатора exit может использоваться для передачи кода завершения. В нашем примере exit 2 передает код завершения в ситуации, когда команда не выполняется, exit 1 — в ситуации, когда файл не удалось найти, и exit 0 — в ситуации, когда файл найден. Если нет явного оператора exit, кодом завершения командного файла является код завершения последней выполняемой команды.Что произойдет, если в вашем текущем каталоге есть программа под именем test
test не является встроенной командой.)$ echo 'echo hello' >test
$ cx test
$ which which
hello
./which
$
Вывод: требуется больший контроль. Можно запустить команду which
test в текущем каталоге), чтобы определить полное имя для test и задать его явно. Но это не лучшее решение, поскольку команда test может присутствовать в различных каталогах в разных версиях системы, а команда which зависит от sed и echo, так что необходимо указать и их полные имена. Можно поступить проще — установить значение PATH в командном файле так, чтобы поиск команд осуществлялся только в /bin и /usr/bin. Конечно, это возможно только в команде which, причем прежнее значение PATH следует сохранить для определения последовательности каталогов при поиске.$ cat which
# which cmd: which cmd in PATH is executed, final version
opath=$PATH
PATH=/bin:/usr/bin
case $# in
0) echo 'Usage: which command' 1>&2; exit 2
esac
for i in `echo $opath | sed 's/^:/.:/
s/::/:.:/g
s/ :$/:./
s/:/ /g'`
do
if test -f $i/$1 # this is /bin/test
then # or /usr/bin/test only
echo $i/$1
exit 0 # found it
fi
done
exit 1 # not found
$
Теперь команда which
test (sed или echo) среди каталогов, входящих в PATH.$ ls -l test
-rwxrwxrwx 1 you 11 Oct 1 06:55 test
$ which which
/usr/you/bin/which
$ which test
./test
$ rm test
$ which test
/bin/test
$
В языке shell
|| и &&, использование которых часто более компактно и удобно, чем оператора if. Например, операция || может заменить некоторые операторы if:test -f имя_файла || echo имя_файла не существует
эквивалентно
if test ! -f имя_файла
then
echo имя файла не существует
fi
Операция ||
||. Если ее код завершения 0 (успех), справа от || команда игнорируется. Если команда слева возвращает другое значение (неудача), выполняется команда справа, и значение всего выражения есть код завершения правой команды. Иными словами, || представляет собой обычную операцию ИЛИ, которая не выполняет свою правую часть, если левая часть завершилась успешно. Соответственно && есть обычная операция И, выполняющая свою правую часть, только если левая часть завершилась успешно.Почему в команде which
PATH из opath?Если в языке shell
esac для завершения оператора case и fi для завершения оператора if, почему для завершения оператора do применяется done?