Bakın! Endüstri gücü 12-line ... teknik olarak bash ve zsh-portatif kabuk fonksiyonu, sizin ~/.bashrc
veya ~/.zshrc
başlangıçtaki komut dosyasını sadık bir şekilde seviyor :
# void +path.append(str dirname, ...)
#
# Append each passed existing directory to the current user's ${PATH} in a
# safe manner silently ignoring:
#
# * Relative directories (i.e., *NOT* prefixed by the directory separator).
# * Duplicate directories (i.e., already listed in the current ${PATH}).
# * Nonextant directories.
+path.append() {
# For each passed dirname...
local dirname
for dirname; do
# Strip the trailing directory separator if any from this dirname,
# reducing this dirname to the canonical form expected by the
# test for uniqueness performed below.
dirname="${dirname%/}"
# If this dirname is either relative, duplicate, or nonextant, then
# silently ignore this dirname and continue to the next. Note that the
# extancy test is the least performant test and hence deferred.
[[ "${dirname:0:1}" == '/' &&
":${PATH}:" != *":${dirname}:"* &&
-d "${dirname}" ]] || continue
# Else, this is an existing absolute unique dirname. In this case,
# append this dirname to the current ${PATH}.
PATH="${PATH}:${dirname}"
done
# Strip an erroneously leading delimiter from the current ${PATH} if any,
# a common edge case when the initial ${PATH} is the empty string.
PATH="${PATH#:}"
# Export the current ${PATH} to subprocesses. Although system-wide scripts
# already export the ${PATH} by default on most systems, "Bother free is
# the way to be."
export PATH
}
Anlık zafer için kendinizi hazırlayın. Öyleyse, bunu yapmaktan ve en iyisini ummak yerine:
export PATH=$PATH:~/opt/bin:~/the/black/goat/of/the/woods/with/a/thousand/young
Bunu yapın ve gerçekten istese de istemeseniz de, en iyisini elde etme garantisi verin:
+path.append ~/opt/bin ~/the/black/goat/of/the/woods/with/a/thousand/young
Çok İyi, "En İyi" yi tanımlayın.
Akıntıya güvenli bir şekilde ekleme ve hazırlık yapma ${PATH}
, genellikle olduğu gibi önemsiz bir mesele değildir. Uygun ve görünüşte mantıklı olsa da, formun tek gömlekleri aşağıdakilerle export PATH=$PATH:~/opt/bin
şeytani komplikasyonları davet eder:
Yanlışlıkla ilgili dizin isimleri (örneğin, export PATH=$PATH:opt/bin
). İken bash
ve zsh
sessizce kabul ve çoğunlukla göreceli dirnames görmezden çoğu durumlarda, göreli dirnames biri tarafından öneki h
veya t
utanç verici hem neden (ve muhtemelen diğer kötü karakterler) Masaki Kobayashi'nin ala kendilerini sakatlamaya seminal 1962 başyapıt Harakiri :
# Don't try this at home. You will feel great pain.
$ PATH='/usr/local/bin:/usr/bin:/bin' && export PATH=$PATH:harakiri && echo $PATH
/usr/local/bin:/usr/bin:arakiri
$ PATH='/usr/local/bin:/usr/bin:/bin' && export PATH=$PATH:tanuki/yokai && echo $PATH
binanuki/yokai # Congratulations. Your system is now face-up in the gutter.
Yanlışlıkla yinelenen dizin isimleri. Yinelenen ${PATH}
dizin adları büyük ölçüde zararsız olsa da, istenmeyen, hantal, hafif derecede verimsizdir, hata ayıklamayı engeller ve sürücü aşınmasını teşvik eder - bu cevabı benzer. NAND tarzı SSD'ler ( elbette ) okuma aşınmasına karşı bağışıklık kazanırken, HDD'ler değildir. Her denenen komutta gereksiz dosya sistemine erişim , aynı tempoda gereksiz okuma kafası aşınması anlamına gelir. Yinelenenler, iç içe geçmiş alt işlemlerde iç içe kabuklar çağırırken özellikle sıra dışıdır; bu noktada, gibi görünüşte masum olan tek gömlekleri export PATH=$PATH:~/wat
, ${PATH}
Cehennem Yedinci Çemberi'ne hızla patlarlar PATH=/usr/local/bin:/usr/bin:/bin:/home/leycec/wat:/home/leycec/wat:/home/leycec/wat:/home/leycec/wat
. Bunun üzerine ek dizinler eklerseniz, yalnızca Beelzebubba size yardımcı olabilir. (Bunun değerli çocuklarınıza olmasına izin vermeyin. )
- Yanlışlıkla eksik dizin isimleri. Yine, eksik
${PATH}
dizinler büyük ölçüde zararsız olsa da, aynı zamanda genellikle istenmeyen, hantal, hafif derecede verimsiz, hata ayıklama özelliğini engelleyen ve sürücü aşınmasını artıran unsurlardır.
Ergo, yukarıda tanımlanmış kabuk işlevi gibi dostane bir otomasyon. Kendimizi kendimizden kurtarmalıyız.
Ama ... Neden "+ path.append ()"? Neden Basitçe append_path ()?
Uyuşmazlık için (örneğin, ${PATH}
başka bir yerde tanımlanmış olan geçerli veya sistem çapındaki kabuk işlevlerinde dış komutlarla ), kullanıcı tanımlı kabuk işlevleri, ideal olarak , standart komut temel adları tarafından desteklenen bash
ve zsh
ancak başka şekilde yasaklanan benzersiz alt dizilerle ön eklenir veya eklenir +
.
Hey. İşe yarıyor. Beni yargılama.
Ama ... Neden "+ path.append ()"? Neden "+ path.prepend ()" değil?
Çünkü ${PATH}
akıntıya ekleme yapmak, akıntıya hazırlık yapmaktan daha güvenli olduğundan ${PATH}
, her şey asla eşit olmadıkları için eşit olur. Kullanıcıya özgü komutlarla sistem genelinde komutları geçersiz kılmak, en iyi ihtimalle sağlıksız ve en kötü ihtimalle çılgınca olabilir. Örneğin, Linux altında, aşağı havzadaki uygulamalar genellikle standart olmayan türev ya da alternatiflerden ziyade GNU coreutils komut çeşitlerini beklerler .
Bununla birlikte, kesinlikle bunun için geçerli kullanım durumları vardır. Eşdeğer +path.prepend()
işlevi tanımlamak önemsizdir. Sans prolix gizliliği, onun ve onun ortak akıl sağlığı için:
+path.prepend() {
local dirname
for dirname in "${@}"; do
dirname="${dirname%/}"
[[ "${dirname:0:1}" == '/' &&
":${PATH}:" != *":${dirname}:"* &&
-d "${dirname}" ]] || continue
PATH="${dirname}:${PATH}"
done
PATH="${PATH%:}"
export PATH
}
Ama ... Neden Gilles değil?
Gilles ' kabul edilen cevabı başka yerde bir genel durumda etkileyici uygunudur 'agnostik İdempotent append kabuk' . Ortak bir durumda bash
ve zsh
ile hiçbir istenmeyen sembolik Ancak performans cezası böylece üzer yapmak için gerekli Gentoo RICER içimde. İstenmeyen sembolik bağların varlığında bile, add_to_PATH()
argüman başına bir alt kabuğun çatallanmasının , sembolik bağlantı kopyalarının potansiyel olarak eklenmesine değip değmeyeceği tartışmalıdır.
Hatta sembolik bağlantı kopukluklarının bile ortadan kaldırılmasını talep eden sıkı kullanım durumları için, bu özel zsh
değişken, verimli olmayan çatallardan ziyade verimli yerleşikler aracılığıyla bunu yapar:
+path.append() {
local dirname
for dirname in "${@}"; do
dirname="${dirname%/}"
[[ "${dirname:0:1}" == '/' &&
":${PATH}:" != *":${dirname:A}:"* &&
-d "${dirname}" ]] || continue
PATH="${PATH}:${dirname}"
done
PATH="${PATH#:}"
export PATH
}
Orijinalin *":${dirname:A}:"*
yerine not alın *":${dirname}:"*
. dahil pek çok kabuğun altında ne yazık ki bulunmayan :A
bir harika . Alıntı yapmak için :zsh
bash
man zshexpn
A : Bir dosya adını a
değiştirici gibi mutlak bir yola dönüştürün ve ardından realpath(3)
sembolik bağları çözmek için sonucu kütüphane işlevinden geçirin. Not: Bir realpath(3)
kütüphane işlevine sahip olmayan sistemlerde , sembolik bağlantılar çözülmez, bu sistemler üzerinde a
ve A
eşdeğerdir.
Daha fazla soru yok.
Rica ederim. Güvenli bombanın keyfini çıkarın. Şimdi bunu hak ettin.