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


AliExpress RU&CIS

В давние времена многоархитектурных 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 — это встроенная в них команда.

Приходилось ли вам, при работе в Unix, решать какие-то задачи, необычным образом пользуясь исключительно встроенными командами оболочки?




Комментарии (13):

  1. saboteur_kiev
    /#23011568 / +2

    for (pe in $candidates)

    В каких шеллах такая конструкция работает?

    builtin cd $pe >[1=] >[2=] && tpath=($tpath $pe)

    что в данном примере означает [1=] и [2=]? или тогда не было /dev/null (как-то маловероятно… )

    В какое время автор писал тогда скрипты и на каком именно шелле и есть ли сейчас шелл актуальный, где это будет работать)?

    • ghostinushanka
      /#23011974

      Вот этот шелл (гитхаб) использовался.

      П.С. На правах личного мнения — надоели ненужные статьи от РУВДС.

      • JohurN
        /#23012036

        Мы всегда готовы услышать предложения по более интересным темам. Если вам хочется увидеть в нашем блоге нужную вам тематику - обязательно пишите.

        • TheSprightlyDuke
          /#23012206

          Лично мне хотелось бы видеть статьи не требующие тега «Перевод». Проанализируйте, сделайте свои выводы, поищите допы, укажите «по мотивам» + ссылку — это дело.

          А плодить такие переводные статейки, чистой воды инфоповод, если не сказать самореклама.

          • JohurN
            /#23012226

            Спасибо, что пишите об этом, это правда важно. Мы будем стараться в этом направлении. Когда есть отклик от читателей, всегда легче понять в какую сторону развиваться.

            • TheSprightlyDuke
              /#23012236

              Молодцы, что отвечаете (понятно, что нет нужды отвечать всегда и на всё). Многие аналогичные блоги молчат или раз в сто лет выдавливают примитивы типа «Спасибо, стараемся». Что нормально так добавляет негатива к отношению к ним.

              • JohurN
                /#23012246

                На самом деле мы хотели организовать пост или тему, формата - расскажите, что бы вас было интересно увидеть на хабре.. Однако есть момент, что это может быть не очень адекватно воспринято, посчитают за сбор тем на рекламу.

                Тем не менее, мы бы хотели поддерживать и улучшать контент на хабре..что без обратной связи вообще невозможно сделать.

                Так что, если у вас есть тематика/область (не темы) обязательно пишите, все учтём.

                • TheSprightlyDuke
                  /#23012278

                  Если правила Хабра позволят вам это сделать, прямо такую статью и напишите «Помогите с темами статей для вас», в ней прямо так и напишите «Не подумайте чего плохого, просим помочь и в комментариях написать темы, которые Вы хотели бы видеть, а так же формат подачи» итд. Сделайте это в лучший день и час, и успех.

                  Не копайте глубже, чем достаточно, будьте проще и ближе :)

                  • JohurN
                    /#23012356

                    Спасибо, что не проходите мимо :) обязательно попробуем написать такой материал, чтобы как-то пообщаться с аудиторией и привнести классный контент.!

        • saboteur_kiev
          /#23013326

          Подобного рода статьи, они и историю не особо раскрывают, поскольку данный способ — это местечковое решение, которое и тогда можно было иначе сделать, и сейчас совершенно невостребованное.
          Если это перевод ИТ истории, то хотелось бы статью, а не краткую заметку…
          Если это техническая фича, то хотелось бы более актуальную.

          • MRD000
            /#23014112

            мне кажется толк может быть, потому что это показывает нестандартные решения. это может засесть в голове и потом похожая тема где-то понадобится.
            но ясно, что любая статья для кого-то полезна, а для кого-то нет. кто-то разаивает знания, а кто-то ищет триллер-рассказ и т.п.

            • saboteur_kiev
              /#23015836

              В статье решается задача, но вся суть исключительно в том, что вместо test используется cd, а сам скрипт и проблема — вообще не совсем о том. То есть статью можно уменьшить до одного предложения.
              Вдобавок на самом деле в GNU/Linux подобную проблему решили тем, что многие внутренние команды шела дублируются GNU утилитами — тот же test доступен в виде /usr/bin/test и /usr/bin/[

              • MRD000
                /#23016400

                Любой фильм можно тоже сократить до 10 минут… Кстати, иногда в ролике к фильму про весь фильм рассказывают, так что даже смотреть не нужно.