Необычный способ использования встроенных команд оболочки для выяснения того, какие директории существуют в системе

Kate

Administrator
Команда форума
В давние времена многоархитектурных Unix-окружений разработчики дистрибутивов не могли прийти к единому мнению о том, что должно быть в $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, находится в $candidates
path=`{ 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 — это встроенная в них команда.


Источник статьи: https://habr.com/ru/company/ruvds/blog/554298/
 
Сверху