it-swarm.asia

Henüz orada değilse $ PATH dizinini ekleyin

Herhangi biri henüz bulunmamışsa $ PATH dizinine eklemek için bash işlevi yazmış olan var mı?

Genelde PATH'a şöyle bir şey eklerim:

export PATH=/usr/local/mysql/bin:$PATH

PATH'imi .bash_profile içinde oluşturursam, içinde bulunduğum oturum bir oturum açma oturumu olmadığı sürece okunmaz - bu her zaman doğru değildir. PATH'imi .bashrc içinde oluşturursam, her bir alt kabukla çalışır. Böylece bir Terminal penceresi başlatıp ardından ekranı çalıştırıp ardından bir Shell betiği çalıştırdığımda, alıyorum:

$ echo $PATH
/usr/local/mysql/bin:/usr/local/mysql/bin:/usr/local/mysql/bin:....

add_to_path() adında bir bash işlevi oluşturmaya çalışacağım, eğer sadece orada değilse dizini ekler. Ancak, eğer birileri zaten böyle bir şey yazmışsa (veya bulmuşsa), bunun üzerine zaman harcamam.

125
Doug Harris

Benim .bashrc'den:

pathadd() {
    if [ -d "$1" ] && [[ ":$PATH:" != *":$1:"* ]]; then
        PATH="${PATH:+"$PATH:"}$1"
    fi
}

PATH zaten dışa aktarılmış olarak işaretlenmiş olmalıdır, bu nedenle yeniden ihracat gerekmez. Bu, dizinin var olup olmadığını denetler ve eklemeden önce bir dizin olup olmadığını umursamadığınız bir dizindir.

Ayrıca, bu yeni dizini yolun sonuna ekler; Başlangıçta yukarıdaki PATH="$1${PATH:+":$PATH"}" satırı yerine PATH= kullanın.

123
Gordon Davisson

Gordon Davisson'ın cevabını genişleterek, bu çoklu argümanları destekliyor

pathappend() {
  for ARG in "[email protected]"
  do
    if [ -d "$ARG" ] && [[ ":$PATH:" != *":$ARG:"* ]]; then
        PATH="${PATH:+"$PATH:"}$ARG"
    fi
  done
}

Böylece, path1 path2 path3'ü pathappend yapabilirsiniz ...

Hazırlamak için

pathprepend() {
  for ((i=$#; i>0; i--)); 
  do
    ARG=${!i}
    if [ -d "$ARG" ] && [[ ":$PATH:" != *":$ARG:"* ]]; then
        PATH="$ARG${PATH:+":$PATH"}"
    fi
  done
}

Pathappend'e benzer şekilde yapabilirsiniz

pathprepend yol1 yol2 yol3 ...

İşte cevabım ila bu sor Doug Harris'in fonksiyonunun yapısı ile birlikte. Bash düzenli ifadelerini kullanır:

add_to_path ()
{
    if [[ "$PATH" =~ (^|:)"${1}"(:|$) ]]
    then
        return 0
    fi
    export PATH=${1}:$PATH
}
12

Bunu seçilen cevaba yapılan yorumlara ekleyin, ancak yorumlar PRE formatını desteklemiyor gibi görünüyor, bu nedenle cevabı buraya ekleyin:

@ gordon-davisson Ben gereksiz alıntı ve birleştirme büyük bir hayranı değilim. Bir bash sürümü> = 3 kullandığınızı varsayarsak, bunun yerine bash'in yerleşik regex'lerinde kullanabilir ve şunu yapabilirsiniz:

pathadd() {
    if [ -d "$1" ] && [[ ! $PATH =~ (^|:)$1(:|$) ]]; then
        PATH+=:$1
    fi
}

Bu, dizinde veya PATH'ta boşlukların olduğu durumları doğru şekilde işler. Bash'ın regex motorunda yerleşik olarak bulunmasının yeterince yavaş olup olmadığına dair bazı sorular var.

10
idempotent_path_prepend ()
{
    PATH=${PATH//":$1"/} #delete any instances in the middle or at the end
    PATH=${PATH//"$1:"/} #delete any instances at the beginning
    export PATH="$1:$PATH" #prepend to beginning
}

$ PATH'nizin başında tam olarak bir kez görünmesi için $ HOME/bin uygulamasına ihtiyaç duyduğunuzda ve başka hiçbir yerde olmadığınızda, başka hiçbir şey kabul etmeyin.

7
Russell

İşte gereksiz girişlerden kurtulmanın ek avantajına sahip alternatif bir çözüm:

function pathadd {
    PATH=:$PATH
    PATH=$1${PATH//:$1/}
}

Bu işlevin tek argümanı PATH'a hazırlanmıştır ve aynı dizgenin ilk örneği mevcut yoldan kaldırılmıştır. Başka bir deyişle, dizin yolda zaten mevcutsa, kopya olarak eklemek yerine öne doğru yükseltilir.

İşlev, tüm girişlerin önde bir sütunu olmasını sağlamak için yola bir sütun hazırlayarak ve ardından o girdi kaldırılmış olarak varolan yola yeni giriş hazırlayarak çalışır. Son bölüm bash ${var//pattern/sub} notasyonu kullanılarak gerçekleştirilir; Daha fazla ayrıntı için bash manual bakınız.

6
Rob Hague

Hazırlık için, Russell'ın çözümünü seviyorum, ama küçük bir hata var: "/ bin" gibi bir şeyi "/ sbin:/usr/bin:/var/usr/bin:/usr/local yoluna hazırlamaya çalışırsanız/bin:/usr/sbin "bu"/bin: "ifadesini 3 kez değiştirir (gerçekten eşleşmediği zaman). Bunun için bir düzeltme @ gordon-davisson gelen çözüm ekleyerek, şunu alıyorum:

path_prepend() {
    if [ -d "$1" ]; then
        PATH=${PATH//":$1:"/:} #delete all instances in the middle
        PATH=${PATH/%":$1"/} #delete any instance at the end
        PATH=${PATH/#"$1:"/} #delete any instance at the beginning
        PATH="$1${PATH:+":$PATH"}" #prepend $1 or if $PATH is empty set to $1
    fi
}
5
PeterS6g

İşte benim (eski laboratuarımın sistemi olan Oscar, yıllar önce Oscar tarafından yazıldığı sanırım), yıllardır bashrc'imdeydi. Yeni dizini istediğiniz gibi hazırlamanıza veya eklemenize izin vermenin yararı vardır:

pathmunge () {
        if ! echo $PATH | /bin/egrep -q "(^|:)$1($|:)" ; then
           if [ "$2" = "after" ] ; then
              PATH=$PATH:$1
           else
              PATH=$1:$PATH
           fi
        fi
}

Kullanımı:

$ echo $PATH
/bin/:/usr/local/bin/:/usr/bin
$ pathmunge /bin/
$ echo $PATH
/bin/:/usr/local/bin/:/usr/bin
$ pathmunge /sbin/ after
$ echo $PATH
/bin/:/usr/local/bin/:/usr/bin:/sbin/
5
terdon

Aşağıdaki gibi basit bir takma ad hile yapmak gerekir:

alias checkInPath="echo $PATH | tr ':' '\n' | grep -x -c "

Tek yaptığı yolu: karakterindeki yolu bölmek ve her bileşeni girdiğiniz argümanla karşılaştırmaktır. Grep tam bir çizgi eşleşmesi olup olmadığını kontrol eder ve sayısını yazdırır.

Örnek kullanım:

$ checkInPath "/usr/local"
1
$ checkInPath "/usr/local/sbin"
1
$ checkInPath "/usr/local/sbin2"
0
$ checkInPath "/usr/local/" > /dev/null && echo "Yes" || echo "No"
No
$ checkInPath "/usr/local/bin" > /dev/null && echo "Yes" || echo "No"
Yes
$ checkInPath "/usr/local/sbin" > /dev/null && echo "Yes" || echo "No"
Yes
$ checkInPath "/usr/local/sbin2" > /dev/null && echo "Yes" || echo "No"
No

Echo komutunu addToPath veya benzeri bir takma ad/işlev ile değiştirin.

4
nagul

İşte çırptığım şey:

add_to_path ()
{
    path_list=`echo $PATH | tr ':' ' '`
    new_dir=$1
    for d in $path_list
    do
        if [ $d == $new_dir ]
        then
            return 0
        fi
    done
    export PATH=$new_dir:$PATH
}

Şimdi .bashrc içinde var:

add_to_path /usr/local/mysql/bin

Özgünümün boşluk içeren dizinleri nasıl işlemeyeceği hakkındaki yorumdan sonra güncellenmiş sürümü (- bu soru beni IFS) kullanarak işaret ediyor:

add_to_path ()
{
    new_dir=$1
    local IFS=:
    for d in $PATH
    do
        if [[ "$d" == "$new_dir" ]]
        then
            return 0
        fi
    done
    export PATH=$new_dir:$PATH
}
2
Doug Harris
2
Jonathan Leffler

Bu yol iyi çalışıyor:

if [[ ":$PATH:" != *":/new-directory:"* ]]; then PATH=${PATH}:/new-directory; fi
1
user2425755
function __path_add(){  
if [ -d "$1" ] ; then  
    local D=":${PATH}:";   
    [ "${D/:$1:/:}" == "$D" ] && PATH="$PATH:$1";  
    PATH="${PATH/#:/}";  
    export PATH="${PATH/%:/}";  
fi  
}  
1
GreenFox

Sürümlerim boş yollar konusunda daha az dikkatli ve geçerli olan yollarda ve dizinlerin burada yayınlananlardan daha az dikkatli olmasına dikkat ediyor, ancak ben preend/append/clean/unique-ify/etc gibi geniş bir ish koleksiyonu buluyorum. Shell, yol manipülasyonunda faydalı olacak şekilde çalışır. Hepsi, şu anki hallerinde, burada: http://Pastebin.com/xS9sgQsX (geri bildirim ve iyileştirmeler çok hoş geldiniz!)

0
andybuckley

İşte POSIX uyumlu bir yol.

# USAGE: path_add [include|prepend|append] "dir1" "dir2" ...
#   prepend: add/move to beginning
#   append:  add/move to end
#   include: add to end of PATH if not already included [default]
#          that is, don't change position if already in PATH
# RETURNS:
# prepend:  dir2:dir1:OLD_PATH
# append:   OLD_PATH:dir1:dir2
# If called with no paramters, returns PATH with duplicate directories removed
path_add() {
    # use subshell to create "local" variables
    PATH="$(path_unique)"
    export PATH="$(path_add_do "[email protected]")"
}

path_add_do() {
    case "$1" in
    'include'|'prepend'|'append') action="$1"; shift ;;
    *)                            action='include'   ;;
    esac

    path=":$PATH:" # pad to ensure full path is matched later

    for dir in "[email protected]"; do
        #       [ -d "$dir" ] || continue # skip non-directory params

        left="${path%:$dir:*}" # remove last occurrence to end

        if [ "$path" = "$left" ]; then
            # PATH doesn't contain $dir
            [ "$action" = 'include' ] && action='append'
            right=''
        else
            right=":${path#$left:$dir:}" # remove start to last occurrence
        fi

        # construct path with $dir added
        case "$action" in
            'prepend') path=":$dir$left$right" ;;
            'append')  path="$left$right$dir:" ;;
        esac
    done

    # strip ':' pads
    path="${path#:}"
    path="${path%:}"

    # return
    printf '%s' "$path"
}

# USAGE: path_unique [path]
# path - a colon delimited list. Defaults to $PATH is not specified.
# RETURNS: `path` with duplicated directories removed
path_unique() {
    in_path=${1:-$PATH}
    path=':'

    # Wrap the while loop in '{}' to be able to access the updated `path variable
    # as the `while` loop is run in a subshell due to the piping to it.
    # https://stackoverflow.com/questions/4667509/Shell-variables-set-inside-while-loop-not-visible-outside-of-it
    printf '%s\n' "$in_path" \
    | /bin/tr -s ':' '\n'    \
    | {
            while read -r dir; do
                left="${path%:$dir:*}" # remove last occurrence to end
                if [ "$path" = "$left" ]; then
                    # PATH doesn't contain $dir
                    path="$path$dir:"
                fi
            done
            # strip ':' pads
            path="${path#:}"
            path="${path%:}"
            # return
            printf '%s\n' "$path"
        }
}

Guillaume Perrault-Archambault 'ın cevabı bu soruya ve mike511 ' nin cevabı bu soruya yazılmıştır.

GÜNCELLEME 2017-11-23: @Scott başına sabit hata

0
go2null

Bu komut dosyası $PATH sonuna eklemenizi sağlar:

PATH=path2; add_to_PATH after path1 path2:path3
echo $PATH
path2:path1:path3

Veya $PATH dosyasının başına şunu ekleyin:

PATH=path2; add_to_PATH before path1 path2:path3
echo $PATH
path1:path3:path2

# Add directories to $PATH iff they're not already there
# Append directories to $PATH by default
# Based on https://unix.stackexchange.com/a/4973/143394
# and https://unix.stackexchange.com/a/217629/143394
add_to_PATH () {
  local prepend  # Prepend to path if set
  local prefix   # Temporary prepended path
  local IFS      # Avoid restoring for added laziness

  case $1 in
    after)  shift;; # Default is to append
    before) prepend=true; shift;;
  esac

  for arg; do
    IFS=: # Split argument by path separator
    for dir in $arg; do
      # Canonicalise symbolic links
      dir=$({ cd -- "$dir" && { pwd -P || pwd; } } 2>/dev/null)
      if [ -z "$dir" ]; then continue; fi  # Skip non-existent directory
      case ":$PATH:" in
        *":$dir:"*) :;; # skip - already present
        *) if [ "$prepend" ]; then
           # ${prefix:+$prefix:} will expand to "" if $prefix is empty to avoid
           # starting with a ":".  Expansion is "$prefix:" if non-empty.
            prefix=${prefix+$prefix:}$dir
          else
            PATH=$PATH:$dir  # Append by default
          fi;;
      esac
    done
  done
  [ "$prepend" ] && PATH=$prefix:$PATH
}
0
Tom Hale

Özel bir değişkenin ayarlanıp ayarlanmadığını kontrol edebilirsiniz, aksi takdirde ayarlayın ve ardından yeni girişleri ekleyin:

if [ "$MYPATHS" != "true" ]; then
    export MYPATHS="true"
    export PATH="$PATH:$HOME/bin:"

    # Java stuff
    export Java_HOME="$(/usr/libexec/Java_home)"
    export M2_HOME="$HOME/Applications/Apache-maven-3.3.9"
    export PATH="$Java_HOME/bin:$M2_HOME/bin:$PATH"

    # etc...
fi

Tabii ki, bu girişler /etc/profile gibi başka bir komut dosyası tarafından eklenirse yine de kopyalanabilir.

0
David Kennedy

Perl one liner kullanabilirsiniz:

appendPaths() { # append a group of paths together, leaving out redundancies
    # use as: export PATH="$(appendPaths "$PATH" "dir1" "dir2")
    # start at the end:
    #  - join all arguments with :,
    #  - split the result on :,
    #  - pick out non-empty elements which haven't been seen and which are directories,
    #  - join with :,
    #  - print
    Perl -le 'print join ":", grep /\w/ && !$seen{$_}++ && -d $_, split ":", join ":", @ARGV;' "[email protected]"
}

İşte bash içinde:

addToPath() { 
    # inspired by Gordon Davisson, http://superuser.com/a/39995/208059
    # call as: addToPath dir1 dir2
    while (( "$#" > 0 )); do
    echo "Adding $1 to PATH."
    if [[ ! -d "$1" ]]; then
        echo "$1 is not a directory.";
    Elif [[ ":$PATH:" == *":$1:"* ]]; then
        echo "$1 is already in the path."
    else
            export PATH="${PATH:+"$PATH:"}$1" # ${x:-defaultIfEmpty} ${x:+valueIfNotEmpty}
    fi
    shift
    done
}
0
dpatru

Biraz değiştirdim Gordon Davisson'ın cevabı eğer mevcut değilse, geçerli dizini kullanmak için. Yani sadece padd yapabilirsiniz PATH eklemek istediğiniz dizinden.

padd() {
  current=`pwd`
  p=${1:-$current}
  if [ -d "$p" ] && [[ ":$PATH:" != *":$p:"* ]]; then
      PATH="$p:$PATH"
  fi
}
0
Thorsten Lorenz