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.
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.
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 ...
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.
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.
İş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.
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
}
İş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/
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.
İş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
}
Bu yol iyi çalışıyor:
if [[ ":$PATH:" != *":/new-directory:"* ]]; then PATH=${PATH}:/new-directory; fi
function __path_add(){
if [ -d "$1" ] ; then
local D=":${PATH}:";
[ "${D/:$1:/:}" == "$D" ] && PATH="$PATH:$1";
PATH="${PATH/#:/}";
export PATH="${PATH/%:/}";
fi
}
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!)
İş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
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
}
Ö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.
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
}
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
}