$PATH
. Базовые вещи, вроде /bin
и
/usr/bin
, были везде одинаковыми, но у каждого
дистрибутива был собственный набор дополнительных директорий
(у
Solaris их, например, было много). Кроме того у разных
локальных вычислительных групп было различное видение того, где
должны размещаться локальные программы. Например в
/usr/local/bin
, в /local/bin
, в
/opt/<something>/bin
, в
/<group>/bin
и так далее. Всё это усложняло мне
жизнь, так как я занимался
поддержкой общего набора dot-файлов, используемых во всех
Unix-системах, за которые я отвечал, и мне не хотелось бы, чтобы
моя переменная $PATH
представляла бы собой огромный
список, содержащий пути ко всем необходимым директориям каждой из
систем. Поэтому мне нужно было убирать всё лишнее из гигантского
базового списка директорий, которые могли присутствовать в
$PATH
, оставляя там лишь те директории, которые
существовали в текущей системе. А чтобы ещё сильнее усложнить эту
задачу, мне хотелось использовать для этого только команды,
встроенные в оболочку, и это при работе с
оболочкой, где test
встроенной командой не
является.К моему счастью, есть одна команда, которая должна быть встроенной в оболочку и при этом даёт сбой в том случае, если директории не существует (или если пользователь не может с ней работать). Это команда
cd
. Использование cd
в качестве
замены 'test -d'
это решение немного странное, но
работоспособное. В моей оболочке были настоящие списки, поэтому я
мог добиться того, что мне нужно, примерно так:
# то, что может попасть в $PATH, находится в $candidatespath=`{ tpath=()for (pe in $candidates)builtin cd $pe >[1=] >[2=] && tpath=($tpath $pe)echo $tpath }
(С относительными путями этот код не работает, но в моей переменной
$PATH
таких путей не было.)Так как во всех оболочках обязательно должна быть встроенная команда
cd
, тот же подход можно было использовать
практически во всех оболочках. Bourne-подобные оболочки, правда,
усложняли задачу по сборке $PATH
. Там, как минимум,
нужно было добавлять :'s
между элементами (cf)
и, возможно, в эквиваленте $candidates
для таких
оболочек нужно было бы использовать :'s
между
записями, что привело бы к необходимости разделять записи,
основываясь на этой конструкции.(В оболочке Bourne я представил бы
$candidates
в виде
строки, заключённой в кавычки, элементы которой разделены
пробелами, так как работать с таким списком директорий гораздо
проще. Правда, при таком подходе я не смог бы обрабатывать
$PATH-записи, содержащие пробелы, но таких записей в
$PATH
обычно не бывает.)Использование
cd
вышеописанным образом это, по сути,
хак, но хаки это то, к чему мы вынуждены прибегать в
минималистичных окружениях оболочек, когда необходимо, для решения
неких задач, обойтись без внешних программ. Я же, на самом деле,
написал на C маленькую программу, isdirs
, которая
решала вышеописанную задачу, и использовал её в тех системах, с
которыми я работал достаточно часто для того, чтобы оправдать
компиляцию для них этой программы. А код, в котором использовалась
команда cd
, был чем-то вроде запасного варианта,
применяемого в системах и в ситуациях, в которых я не мог
воспользоваться моей isdirs
.(Этот материал можно счесть чем-то вроде продолжения одной моей статьи про хак командной оболочки Unix, которая тоже связана с кросс-архитектурной средой и с dot-файлами.)
P.S. То, о чём я рассказал, происходило в те времена, когда системы были достаточно медленными для того чтобы тот, кто их обслуживает, стремился бы к тому, чтобы без крайней нужды не пользоваться дополнительными внешними программами в dot-файлах оболочки. Именно поэтому я и решил пользоваться только встроенными командами оболочки вместо того, чтобы выполнять множество вызовов
test
или чего-то подобного. А в большинстве
современных оболочек test
это встроенная в них
команда.Приходилось ли вам, при работе в Unix, решать какие-то задачи, необычным образом пользуясь исключительно встроенными командами оболочки?