PATH'ımı cwd'ye göre dinamik olarak değiştirebilir miyim?


4

$PATHGeçerli çalışma dizinime bağlı olarak ortam değişkenimi değiştirmek istiyorum .

Ben varım deyin /foo/bar/bazve dizinleri vardır /foo/node_modules/.binve /foo/bar/baz/node_modules/.bin. Mümkün olan her ./node_modules/.binözyineyi eklemek isterim $PATH.

Ancak, cdfarklı bir dizine (gibi /foo/bar) girdiğimde, orijinalimin temizliğini $PATHgeri almamı ve sonra ./node_modules/.bintekrar tekrar aramaya başlamayı istiyorum .

(Npm'in sorun izleyicisinden kendi sorumu çözmek istiyorum: Yerel olarak kurulu paketleri PATH'a da ekleyebilir miyiz? )

Not: Mac'tayım, ancak genel bir çözümle ilgileniyorum.

Yanıtlar:


3

Giriş

Seni doğru anladıysam, herhangi dizinleri eklemek istediğiniz olduğu ya da atalarından herhangi."$X/node_modules/.bin"$X$PWD

Bu yazının sonundaki komut dosyası istediğiniz davranışı sağlamalıdır. İstediğiniz her oturumda onu kaynaklamanız gerekir. Dosyayı adlandırırsanız augment_path.sh, bu satırı bilgisayarınıza eklemek .bashrcyeterli olacaktır:

source augment_path.sh

Tartışma

Sanırım Garyjohn'un temel bir yaklaşımı var, ama atalarından ziyade tüm soyundan geliyor.

$PROMPT_COMMANDDeğişken istemi her gösterildiğinde yürütülecek bir komut girmesini sağlar. $PROMPT_COMMAND_OLDOrijinalin $PROMPT_COMMANDgeri yüklenmesine izin vermek için bir değişken ekledim

Muhtemelen gerekli değildir, ancak iyi form için $LAST_WD, dizin değişmediğinde yolu yeniden hesaplamaktan kaçınmak için bir değişken ekleyip test ediyorum . İsterseniz içeren üç satırı da kaldırabilirsiniz LAST_WD.

augment_pathDan işlev taramalar $PWDyukarı her atanın hedef dizinleri arayan ve onu yola bulduğu ekledi.

  • Yola sıralı olarak yerleştirilirler, bu nedenle herhangi bir çakışma olursa bu kadar derin dizin öncelik kazanacaktır. Bunun istenen davranış olduğunu farz ediyorum. Değilse değiştir

    PATH_ADDITION="$PATH_ADDITION:$resolved_target"

    için

    PATH_ADDITION="$resolved_target:$PATH_ADDITION"
  • Ancak, bu dizinlerin tümü yolun geri kalanından öncelikli olacaktır. Yolun geri kalanının öncelikli olmasını istiyorsanız, değiştirin:

    PATH="$PATH_ADDITION:$RAW_PATH"

    için

    PATH="$RAW_PATH:$PATH_ADDITION"

Senaryo

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"

Bu sorunu çözen her birinize teşekkür ederim ve bu derinlemesine cevap için size procrasty teşekkür ederiz. Kabuklu olmayan bir uzman olarak ek açıklamalarınız çok faydalıdır. Çözümünüz tam olarak umduğum gibi çalışıyor (yolun geri kalanından en yüksek önceliğe ve önceliğe sahip en derin dizin. Mükemmel.
Pipo

1

Sanırım aşağıdakileri kendi ~/.bashrcisteğinize dahil edeceksiniz.

Bash ortam değişkeni PROMPT_COMMANDbir komuta ayarlanırsa, bash birincil istemi görüntülemeden önce bu komut yürütülür.

Aşağıdaki kodda PROMPT_COMMAND, bir fonksiyonun adına ayarlanmış doit,. Bu işlev mevcut çalışma dizininin değişip değişmediğini kontrol eder ve eğer öyleyse ilk önce PATHorijinal değerine ayarlar , sonra adlandırılmış bir alt dizinin varlığını kontrol eder node_modules/.bin. Bu alt dizin varsa, işlev onun adını ve altındaki tüm alt dizinleri ekler 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


Üzgünüm, Mac OS X kullandığımı söylemeyi unuttum. Görünüşe göre -printforada kullanamıyorum . Bunun yanında çalışması gerektiğini düşünüyorum ...
Pipo

Yerine -printf ':%p'göre -exec echo -n :{} \;de iş gibi görünüyor, ama hepsi değil echovar s -nve ben şu anda bir Mac erişimi yok. Eğer senin echoyoksa -nveya eşdeğerini, sen ihmal olabilir -nve izleme findile | tr -d '\n'yeni satır kaldırın.
garyjohn

-n iş gibi görünüyor. Bu neredeyse istediğim gibi çalışıyor, ama en derin dizinden tepeye kadar özyinelemeli çalışmıyor ya da yanlış mı yapıyorum? Ben varım Say foo/bar/bazhiçbir daha /foo/bar/baz/node_modules/.binve /foo/node_modules/.bineklenir.
Pipo

0

Bash ile çalışabilirsiniz PROMPT_COMMAND:

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

Bu komut bilgi istemi göründüğünde her zaman uygulanır. Bu nedenle, bir komut bittiğinde her zaman PATHdeğişken değişir. Sonuna ek bir dizin eklenir.

./node_modules/.binGeçerli çalışma dizininde bir dizin yoksa, yol yine de eklenir. Ancak bu sorun değil. Bu aranmamış çukur değildir (çünkü yoktur).

Gösteriye bakın:

$ 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

Bu neredeyse istediğim gibi çalışıyor, ama en derin dizinden tepeye kadar özyinelemeli çalışmıyor ya da yanlış mı yapıyorum? Ben varım Say foo/bar/bazhiçbir daha /foo/bar/baz/node_modules/.binve /foo/node_modules/.bineklenir.
Pipo

@Pipo Doğru şekilde anlamadım. 2 klasör eklemek ister misiniz? Öyleyse ./node_modules/.binve ../../node_modules/.bin? Eğer evet ise, o zaman bunu kullanın PROMPT_COMMAND='[ -z "$X" ] && X=$PATH; PATH=$X:$(pwd)/node_modules/.bin:$(pwd)/../../node_modules/.bin'. Biraz tuhaf görünecekse, $PATHdeğişken ancak istediğiniz gibi çalışması gerekir.
kaos,

Evet, haklısın. Her iki klasörü de eklemek istiyorum, çünkü Düğüm modülleri birbirine yuvalanmış. Teşekkürler, deneyeceğim.
Pipo

Sadece ../../parçanın kodlanmış olduğunu fark ettim . Üzgünüm, /foo/bar/bazörneğimin sadece bir örnek olduğunu söylemeliydim . Gerçekten olabilir herhangi dizin yapısı. @ Pyrocrasty 'nin cevabını şimdi deneyeceğim.
Pipo
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.