PATH'tan bir dizini kaldırma


28

MingW kullanarak wxWidget'ları derlemeye çalışıyorum ve yolumda cygwin var, bu da çatışmaya benziyor. Bu yüzden /d/Programme/cygwin/binPATH değişkeninden kaldırmak istiyorum ve bunu yapmanın zarif bir yolu olup olmadığını merak ediyorum.

Saf yaklaşım onu ​​bir dosyaya yansıtmak, el ile kaldırmak ve kaynaklamak olacaktır, ancak bahse girerim ki bu konuda daha iyi bir yaklaşım vardır.


2
Birçok teknik burada listelenmiştir: stackoverflow.com/questions/370047/…
slm

Yanıtlar:


23

$ PATH değerini "düzenlemek" için standart bir araç yoktur (yani, "yalnızca mevcut olmadığında klasör ekle" veya "bu klasörü kaldır"). Siz sadece uygulayın:

export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

Kalıcı olarak değiştirmek istiyorsanız, herhangi bir .bashrc, bash.bashrc, / etc / profile - sisteminize ve kullanıcı gereksinimlerinize uygun olanı ekleyin. Bununla birlikte, BASH kullanıyorsanız, dizini /home/wrong/dir/PATH değişkeninizden kaldırmak istediğinizi varsayalım: Diyelim ki, sonunda varsayalım:

PATH=$(echo "$PATH" | sed -e 's/:\/home\/wrong\/dir$//')

Yani senin durumunda kullanabilirsin

PATH=$(echo "$PATH" | sed -e 's/:\/d\/Programme\/cygwin\/bin$//')

1
Söz konusu yol PATH değişkeninin başındaysa, en sondaki sütunu eşleştirmeniz gerekir. Bu, PATH değişkenlerinin kolay genel manipülasyonlarını zorlaştıran sinir bozucu bir uyarıdır.
Graeme

4
Çok fazla eğik çizgiyle uğraşırken regex sınırlayıcısını aşağıdaki /gibi bir şeyle değiştirmeyi tercih ederim |: PATH=$(echo "$PATH" | sed -e 's|:/d/Programme/cygwin/bin$||')tüm kaçmayı önlemek için.
Matthias Kuhn

17

Bash:

directory_to_remove=/d/Programme/cygwin/bin
PATH=:$PATH:
PATH=${PATH//:$directory_to_remove:/:}
PATH=${PATH#:}; PATH=${PATH%:}

Bir ara değişken kullanmazsanız /, dizinde yer alan karakterleri, arama metninin sonu olarak işlem görmemeleri için korumanız gerekir .

PATH=:$PATH:
PATH=${PATH//:\/d\/Programme\/cygwin\/bin:/:}
PATH=${PATH#:}; PATH=${PATH%:}

Birinci ve üçüncü satır :, birinci ve son bileşenin özel bir şekilde korunmasından kaçınmak için, arama yolunun her bileşeninin çevrelenmesini sağlamak için oradadır . İkinci satır belirtilen bileşeni kaldırır.


Teşekkürler @Gilles, cevabınız benden dört yerine sadece üç PATH manipülasyonu gerektiren kendi çözümümü bulmamı istedi . * 8 ')
Mark Booth,

8

Burada sunulan diğer seçenekleri göz önünde bulundurduktan ve bazılarının nasıl çalıştığını tam olarak anlamadan sonra, kendi path_removefonksiyonumu geliştirdim .bashrc:

function path_remove {
  # Delete path by parts so we can never accidentally remove sub paths
  PATH=${PATH//":$1:"/":"} # delete any instances in the middle
  PATH=${PATH/#"$1:"/} # delete any instance at the beginning
  PATH=${PATH/%":$1"/} # delete any instance in the at the end
}

Bu, Gilles'un çözümüne oldukça yakın ancak komut satırında kolayca kullanılabilecek bir bash işlevi olarak tamamlandı.

Bir bash işlevi olarak, yolda bir programa ihtiyaç duymadan bir program gibi çalışması ve sadece bash string manipülasyonu için herhangi bir harici program gerektirmemesi avantajlarına sahiptir.

O açılmıyor özellikle bu oldukça sağlam görünen somepath:mypath/mysubpathiçine somepath/mysubpath: koşarsan path_remove mypathbenim önceki yaptığım bir sorun olduğu, path_removeişlevi.

Bash string manipülasyonunun nasıl çalıştığının mükemmel bir açıklaması Advanced Bash-Scripting Guide'da bulunabilir .


6

Böylece, @ gilles ve @ bruno-a (ve diğer birkaç püf noktası) 'nın cevaplarını birleştirerek, başlangıçta meydana gelip gelmediğine bakılmaksızın (her) REMOVE_PART'ı PATH'dan kaldıracak olan bu bir astarla geldim. PATH'in ortası veya sonu

PATH=$(REMOVE_PART="/d/Programme/cygwin/bin" sh -c 'echo ":$PATH:" | sed "s@:$REMOVE_PART:@:@g;s@^:\(.*\):\$@\1@"')

Biraz hantal, ama tek bir vuruşta yapabilmek güzel. ;Birlikte iki ayrı sed komutları katılmak için kullanılır:

  • s@:$REMOVE_PART:@:@g( :$REMOVE_PART:tek olanla değiştirilir :)
  • s@^:\(.*\):\$@\1@ (echo komutuyla eklediğimiz önde gelen ve sondaki iki nokta üstünden çıkarır)

Ve benzer hatlar boyunca, PATH’e bir ADD_PART eklemek için bu tek-liner ile geldim, ancak PATH zaten içermiyorsa

PATH=$(ADD_PART="/d/Programme/cygwin/bin" sh -c 'if echo ":$PATH:" | grep -q ":$ADD_PART:"; then echo "$PATH"; else echo "$ADD_PART:$PATH"; fi')

echo "$PATH:$ADD_PART"ADD_PART'ı başlatmak yerine PATH'nin sonuna eklemek istiyorsanız son parçayı değiştirin .

...

... ya da bunu daha da kolaylaştırmak remove_path_partiçin içeriği olan bir script oluşturun.

echo ":$PATH:" | sed "s@:$1:@:@g;s@^:\(.*\):\$@\1@"

ve prepend_path_partiçeriği ile çağırılan bir betik

if echo ":$PATH:" | grep -q ":$1:"; then echo "$PATH"; else echo "$1:$PATH"; fi

ve append_path_partiçeriği ile çağırılan bir betik

if echo ":$PATH:" | grep -q ":$1:"; then echo "$PATH"; else echo "$PATH:$1"; fi

hepsini çalıştırılabilir yap ve sonra onları şöyle çağır:

  • PATH=$(remove_path_part /d/Programme/cygwin/bin)
  • PATH=$(prepend_path_part /d/Programme/cygwin/bin)
  • PATH=$(append_path_part /d/Programme/cygwin/bin)

Düzgün, söylesem bile kendim :-)


Öneriyi severim, özellikle senaryolardaki fikir.
Devolus

3

Çok daha basit bir astar.

dışa aktarma PATH = `echo $ PATH | tr ":" "\ n" | grep -v "anaconda" | tr "\ n" ":" `


2

Bir yol değişkeninden bir dizini kaldırmak için bir bash işlevi yazmak ilginç bir alıştırmadır.

Dizinleri yollara eklemek / hazırlamak için .bash * dosyalarımda kullandığım bazı işlevler. Varsa, yinelenen girişleri kaldırma erdemine sahipler ve her türlü iki noktadan ayrılmış yol değişkeni (PATH, MANPATH, INFOPATH, ...) ile çalışıyorlar. remove_from işlevi dizini siler.

# {app,pre}pend_to path-var-name dirpath
# remove_from path-var-name dirpath
#
# Functions to manipulate a path-style variable.  {app,pre}pend_to
# both remove any other instances of dirname before adding it to
# the start or end of the path-var-name variable.
#
# Calling example:
#   append_to PATH "/usr/local/bin"
#
# Uses eval to allow target path varname to be passed in.
function remove_from() {
  # add surrounging colons
  eval tmp_path=":\$${1}:"
  # if dir is already there, remove it
  (echo "${tmp_path}" | grep --silent ":${2}:") &&
    tmp_path=`echo "$tmp_path" | sed "s=:${2}:=:=g"`
  # remove surrounding colons
  tmp_path=`echo "$tmp_path" | sed 's=^:==; s=:$=='`
  eval export $1=\"$tmp_path\"
}
function append_to() {
  remove_from "$1" "$2"  # clean the path contents
  eval export $1=\"\$${1}:$2\"
}
function prepend_to() {
  remove_from "$1" "$2"  # clean the path contents
  eval export $1=\"${2}:\$$1\"
}

2

Aşağıda Greg Tarsa'nın çözümündeki kod değiştirildi. Burada yalnızca bash yerleşik komutları kullanılır. Böylece, bir çok çatal () sistemi çağrısı kaydedecektir.

# Calling example:
#   append_to PATH "/usr/local/bin"

function remove_from()
{
    local path="${1}"
    local dir="${2}"
    local -a dirs=()
    local old_ifs="${IFS}"
    IFS=":"
    set -- ${!path}
    while [ "$#" -gt "0" ]
    do
        [ "${1}" != "${dir}" ] && dirs+=("${1}")
        shift
        done
    eval "export ${path}=\"${dirs[*]}\""
    IFS="${old_ifs}"
}

function append_to()
{
    remove_from "${1}" "${2}"
    [ -d "${2}" ] || return
    if [ -n "${!1}" ]
    then
        eval "export ${1}=\"${!1}:${2}\""
    else
        eval "export ${1}=\"${2}\""
    fi
}

function prepend_to()
{
    remove_from "${1}" "${2}"
    [ -d "${2}" ] || return
    if [ -n "${!1}" ]
    then
        eval "export ${1}=\"${2}:${!1}\""
    else
        eval "export ${1}=\"${2}\""
    fi
}

1

Tushar'dan kabul edilen cevabı tamamlamak / iyileştirmek için şunları yapabilirsiniz:

  • eğik çizgi sınırlayıcıları kullanarak PATH'deki eğik çizgilerin dışına çıkmaktan kaçının
  • omit -egereğince seçeneği sed adam sayfası : "hayır -e, --expression, -f veya --file seçenek verilir, daha sonra ilk seçenek olmayan argüman sed komut dosyası olarak alınırsa yorumlamak."
  • gtüm oluşumları kaldırmak için (global) bayrağını kullanın

Sonunda, böyle bir şey verir:

PATH=$(echo "$PATH" | sed 's@:/home/wrong/dir$@@g')

0

Mevcut cevaplar, birden fazla yolu kaldırmam gerektiği için benzer sorunumu çözmüyor. Tüm bu yollar tek bir dizinin alt dizinleridir. Bu durumda, bu bir astar benim için çalışır: ( cygwinörneğin, örüntü içeren tüm yolları kaldırdığını varsayalım cygwin)

pattern=cygwin; export PATH=$(echo $PATH|tr ':' '\n'|sed "\#${pattern}#d" |tr '\n' ':')
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.