4

Я хотел бы изменить переменную среды $PATH зависимости от текущего рабочего каталога.

Скажем, я в /foo/bar/baz и у меня есть каталоги /foo/node_modules/.bin и /foo/bar/baz/node_modules/.bin . Я хотел бы добавить все возможные ./node_modules/.bin рекурсивно к $PATH .

Но когда я cd в другой каталог (например, /foo/bar), я хочу, чтобы мой исходный чистый $PATH был восстановлен, а затем снова начал искать ./node_modules/.bin .

(Я хочу решить свой собственный вопрос из системы отслеживания проблем npm: можем ли мы также добавить локально установленные пакеты в PATH?)

Примечание: я на Mac, но заинтересован в общем решении.

3 ответа3

3

Вступление

Если я вас правильно понимаю, вы хотите добавить любые каталоги "$X/node_modules/.bin" где $X - это $PWD или любой из его предков.

Сценарий в конце этого поста должен дать желаемое поведение. Вы должны получать его в каждом сеансе, где вы хотите. Если вы назовете файл augment_path.sh , то добавления этой строки в ваш .bashrc должно быть достаточно:

source augment_path.sh

обсуждение

Я думаю, что у Гарийона правильный подход, но он ищет всех потомков, а не всех предков.

$PROMPT_COMMAND позволяет указать команду, которая будет выполняться при каждом отображении приглашения. Я добавил переменную $PROMPT_COMMAND_OLD чтобы позволить восстановить исходный $PROMPT_COMMAND

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

Функция augment_path сканирует от $PWD выше, ищет целевые каталоги у каждого предка и добавляет все найденные пути к пути.

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

    PATH_ADDITION="$PATH_ADDITION:$resolved_target"
    

    в

    PATH_ADDITION="$resolved_target:$PATH_ADDITION"
    
  • Однако все эти каталоги будут иметь приоритет над остальной частью пути. Если вы хотите, чтобы остаток пути имел приоритет, измените:

    PATH="$PATH_ADDITION:$RAW_PATH"
    

    в

    PATH="$RAW_PATH:$PATH_ADDITION"
    

скрипт

RAW_PATH="$PATH"
LAST_WD=`pwd`

augment_path() {
    target="node_modules/.bin"
    if [ "$PWD" = "$LAST_WD" ]; then return 0; fi;
    PATH_ADDITION=""
    scandir="$PWD"
    until [ "$scandir" = "" ]; do
    resolved_target="$scandir"/"$target"
    if [ -d "$resolved_target" ]; then
        PATH_ADDITION="$PATH_ADDITION:$resolved_target"
    fi
    scandir="${scandir%/*}"
    done 
    PATH="$PATH_ADDITION:$RAW_PATH"
    LAST_WD=`pwd`
}

PROMPT_COMMAND_OLD="${PROMPT_COMMAND%; augment_path}"
PROMPT_COMMAND="$PROMPT_COMMAND_OLD; augment_path"
1

Я думаю, что размещение следующего в вашем ~/.bashrc будет делать то, что вы хотите.

Если для переменной среды bash PROMPT_COMMAND задана какая-либо команда, эта команда выполняется до того, как bash отобразит основное приглашение.

В приведенном ниже коде PROMPT_COMMAND установлен на имя функции doit . Эта функция проверяет, изменился ли текущий рабочий каталог, и если да, то сначала устанавливает для PATH исходное значение, а затем проверяет наличие подкаталога с именем node_modules/.bin . Если этот подкаталог существует, функция добавляет его имена и все подкаталоги под ним в PATH .

orig_path="$PATH"
prev_pwd=""
doit() {
    if [ "$PWD" != "$prev_pwd" ]; then
        PATH="$orig_path"
        if [ -d "node_modules/.bin" ]; then
            PATH="$PATH$(find $PWD/node_modules/.bin -type d -printf ':%p')"
            # For POSIX compatibility (macOS or other), use:
            # PATH="$PATH$(find $PWD/node_modules/.bin -type d -exec echo -n :{} \;)"
        fi
        prev_pwd="$PWD"
    fi
}
PROMPT_COMMAND=doit

0

Вы можете работать с PROMPT_COMMAND bash:

PROMPT_COMMAND='[ -z "$X" ] && X=$PATH; PATH=$X:$(pwd)/node_modules/.bin'

Эта команда выполняется каждый раз, когда появляется приглашение. Поэтому каждый раз, когда команда завершается, переменная PATH изменяется. Дополнительный каталог добавляется в конец.

Если в текущем рабочем каталоге нет каталога ./node_modules/.bin , путь все равно добавляется. Но это не проблема. Это не поиск корыта (потому что он не существует).

Смотрите демонстрацию:

$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$ PROMPT_COMMAND='[ -z "$X" ] && X=$PATH; PATH=$X:$(pwd)/node_modules/.bin'
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/node_modules/.bin
$ cd test
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/test/node_modules/.bin
$ cd /etc/
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/etc/node_modules/.bin

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .