Однако такое решение проблематично. Пустая строка в PATH
'.'. Поэтому перевод двоеточий в пробелы не слишком удачен — теряется информация о пустых компонентах. Для создания правильного списка каталогов пустую компоненту PATH нужно перевести в точку. Пустая компонента может быть в середине, начале или конце строки, так что вам придется потрудиться, чтобы учесть все возможные случаи:$ echo $PATH | sed 's/^:/./
> s/::/:.:/g
> s/:$/:./
> s/:/ /g'
. /usr/you/bin /bin /usr/bin
$
Мы могли бы записать это с помощью четырех отдельных команд sed
sed производит замены по порядку, можно выполнить все операции за один вызов.После задания каталогов в компонентах PATH
test(1) может вывести сообщение о том, существует ли файл в каждом каталоге. В принципе команда test — одна из самых "неуклюжих" программ UNIX. Например, команда "test -r файл" проверяет, существует ли файл и можно ли его читать; "test -w файл" проверяет, существует ли файл и можно ли в него писать, но в седьмой версии нет команды test -х (хотя в System V и других версиях есть), а именно она нам и нужна. Мы примем, что обращение "test -f файл" будет проверять, существует ли файл и не является ли он каталогом, т.е. представляет ли он собой обычный файл. Но вам следует обратиться к соответствующей странице справочного руководства, поскольку имеет хождение несколько версий.Каждая команда вырабатывает
Поскольку ложь может представлять множество различных значений, причина неудачи обозначается кодом завершения по лжи. Например, команда grep возвращает 0, если произошло сопоставление, 1 — если сопоставления не было, и 2 — в случае ошибки в шаблоне или именах файлов. Каждая программа возвращает код завершения, хотя обычно нас не интересует его значение. Команда test
Интерпретатор хранит код завершения последней программы в переменной $?
$ cmp /usr/you/.profile /usr/you/.profile
$
$ echo $?
0
$ cmp /usr/you/.profile /usr/mary/.profile
/usr/you/.profile /usr/mary/.profile differ: char 6, line 3
$ echo $?
1
$
У некоторых команд, таких, как cmp
grep, есть флаг -s, который заставляет их завершить выполнение с определенным кодом, но подавляет вывод. Оператор if языка shell запускает команды в зависимости от кода завершения некоторой команды, а именно:if команда
then
команды, если условие верно
else
команды, если условие ложно
fi
Местоположение символов перевода строк очень важно: fi
then и else распознаются только после символа перевода строки или точки с запятой.Оператор if
case сопоставление с шаблоном производится самим интерпретатором. В некоторых версиях UNIX, включая System V, test является встроенной командой интерпретатора, поэтому if и test будут выполняться так же быстро, как и case. Если test — не встроенная команда, то операторы case более эффективны, чем операторы if, и следует использовать именно их для поиска шаблонов;$ case "$1" in
hello) command
esac
выполняется быстрее, чем
if test "$1"==hello
then
command
fi
Это одна из причин, по которой в языке shell
case, хотя в большинстве языков программирования использовались бы операторы if. С другой стороны, с помощью оператора case непросто определить, имеется ли право доступа к файлу на чтение; здесь предпочтение следует отдать команде test и оператору if.Итак, теперь мы готовы воспользоваться первой версией команды which
$ cat which
# which cmd: which cmd in PATH is executed, version 1
case $# in
0) echo 'Usage: which command' 1>&2; exit 2
esac