ดูเถิด! 12-line ที่แข็งแกร่งในอุตสาหกรรม...ฟังก์ชั่นเปลือก bash- และ zsh-portable ในทางเทคนิคที่รักสคริปต์ของคุณ~/.bashrc
หรือ~/.zshrc
สคริปต์เริ่มต้นที่เลือกโดยเฉพาะ:
# 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
}
จงเตรียมใจให้พร้อมรับรัศมีภาพทันที จากนั้นแทนที่จะทำสิ่งนี้และหวังว่าจะได้สิ่งที่ดีที่สุด:
export PATH=$PATH:~/opt/bin:~/the/black/goat/of/the/woods/with/a/thousand/young
ทำสิ่งนี้แทนและรับรองว่าจะได้รับสิ่งที่ดีที่สุดไม่ว่าคุณจะต้องการมันหรือไม่ก็ตาม:
+path.append ~/opt/bin ~/the/black/goat/of/the/woods/with/a/thousand/young
ดีมากกำหนด "ดีที่สุด"
การต่อท้ายและต่อเติมอย่างปลอดภัยในปัจจุบัน${PATH}
ไม่ใช่เรื่องเล็ก ๆ น้อย ๆ ที่เกิดขึ้นโดยทั่วไป ในขณะที่ความสะดวกสบายและสมเหตุสมผลดูเหมือนหนึ่งในรูปแบบตอร์ปิโดexport PATH=$PATH:~/opt/bin
เชิญภาวะแทรกซ้อนมารด้วย:
ชื่อเล่นที่สัมพันธ์กันโดยบังเอิญ (เช่นexport PATH=$PATH:opt/bin
) ในขณะที่bash
และzsh
เงียบยอมรับและส่วนใหญ่ไม่สนใจ dirnames ญาติในที่สุดกรณี dirnames ญาตินำหน้าโดยทั้งh
หรือt
(และอาจจะตัวละครที่ชั่วร้ายอื่น ๆ ) สาเหตุทั้งประเจิดประเจ้อทำลายตัวเอง Ala มาซากิโคบายาชิของน้ำเชื้อ 1962 ชิ้นเอกการฆ่าตัวตาย :
# 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.
ชื่อเล่นที่ซ้ำกันโดยบังเอิญ ในขณะที่ชื่อ${PATH}
dirnames ซ้ำ ๆนั้นไม่มีอันตรายส่วนใหญ่พวกมันยังไม่พึงประสงค์ยุ่งยากไม่มีประสิทธิภาพเล็กน้อยขัดขวางการ debuggability และส่งเสริมการสึกหรอของไดรฟ์ - sorta เหมือนคำตอบนี้ ขณะ SSDs NAND สไตล์ ( แน่นอน ) ภูมิคุ้มกันเพื่ออ่านสวมใส่ฮาร์ดดิสก์ไดรฟ์ไม่ได้ การเข้าถึงระบบไฟล์ที่ไม่จำเป็นในทุกคำสั่งที่พยายามหมายถึงการสึกหรอของหัวอ่านที่ไม่จำเป็นในจังหวะเดียวกัน ซ้ำเป็นสอพลอเฉพาะอย่างยิ่งเมื่อการเรียกใช้เปลือกหอยที่ซ้อนกันในกระบวนการย่อยที่ซ้อนกันที่จุดที่ดูเหมือนไม่มีพิษมีภัยหนึ่งสมุทรเหมือนexport PATH=$PATH:~/wat
อย่างรวดเร็วระเบิดเข้าไปในเจ็ดวงกลมของนรกเช่น${PATH}
PATH=/usr/local/bin:/usr/bin:/bin:/home/leycec/wat:/home/leycec/wat:/home/leycec/wat:/home/leycec/wat
มีเพียง Beelzebubba เท่านั้นที่สามารถช่วยคุณได้ถ้าคุณต่อท้ายชื่อเล่นเพิ่มเติมเข้าไป (อย่าปล่อยให้เรื่องนี้เกิดขึ้นกับลูกที่มีค่าของคุณ )
- ชื่อผู้ใช้หายไปโดยไม่ได้ตั้งใจ อีกครั้งในขณะที่ชื่อ
${PATH}
dirnames ที่หายไปนั้นไม่มีอันตรายส่วนใหญ่ แต่โดยทั่วไปแล้วพวกเขายังไม่พึงประสงค์ยุ่งยากยุ่งยากไม่มีประสิทธิภาพเล็กน้อยขัดขวางการ debuggability และส่งเสริมการสึกหรอของไดรฟ์
ดังนั้นระบบอัตโนมัติที่เป็นมิตรเช่นฟังก์ชั่นของเชลล์ที่กำหนดไว้ด้านบน เราต้องช่วยตัวเองให้พ้นจากตัวเราเอง
แต่ ... ทำไม "+ path.append ()" ทำไมไม่เพียงแค่ append_path ()
สำหรับ disambiguity (เช่นมีคำสั่งภายนอกในปัจจุบัน${PATH}
ฟังก์ชั่นเปลือกหรือทั้งระบบที่กำหนดไว้ที่อื่น ๆ ) ที่ผู้ใช้กำหนดฟังก์ชั่นเปลือกจะมีคำนำหน้านึกคิดหรือ suffixed กับสตริงที่ไม่ซ้ำกันโดยได้รับการสนับสนุนbash
และzsh
แต่ห้ามมิฉะนั้นสำหรับ basenames คำสั่งมาตรฐานที่ชอบ - +
พูด
เฮ้ มันได้ผล. อย่าตัดสินฉัน
แต่ ... ทำไม "+ path.append ()" ทำไมไม่ "+ path.prepend ()"
เนื่องจากการต่อท้ายกระแส${PATH}
นั้นปลอดภัยกว่าการต่อท้ายกับ${PATH}
ทุกสิ่งเท่ากันซึ่งไม่เคยเป็น การเอาชนะคำสั่งทั้งระบบด้วยคำสั่งเฉพาะของผู้ใช้นั้นอาจไม่ดีต่อสิ่งที่ดีที่สุดและทำสิ่งที่แย่ที่สุด ภายใต้ Linux ตัวอย่างเช่นแอพพลิเคชั่นแบบดาวน์สตรีมโดยทั่วไปคาดหวังว่าGNU coreutils จะแตกต่างจากคำสั่งแทนที่จะเป็นอนุพันธ์หรือทางเลือกที่ไม่ได้มาตรฐาน
ที่กล่าวว่ามีกรณีใช้อย่างถูกต้องสำหรับการทำเช่นนั้น การกำหนด+path.prepend()
ฟังก์ชั่นที่เทียบเท่านั้นเป็นเรื่องเล็กน้อย Sans prolix nebulosity สำหรับเขาและเธอที่แบ่งปัน:
+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
}
แต่ ... ทำไมต้องไม่ใช่กิลส์?
กิลส์ ' คำตอบที่ได้รับการยอมรับที่อื่นจะดีที่สุดประทับใจในกรณีทั่วไปเป็น'เปลือกผนวก idempotent ไม่เชื่อเรื่องพระเจ้า' ในกรณีที่พบบ่อยของbash
และzsh
มีไม่มี symlinks ที่ไม่พึงประสงค์ แต่ลงโทษประสิทธิภาพที่จำเป็นในการทำเช่นนั้นเศร้าricer Gentooในตัวผม แม้จะadd_to_PATH()
มี symlink ที่ไม่พึงประสงค์ก็ยังเป็นที่ถกเถียงกันว่าการฟอร์กหนึ่ง subshell ต่อการโต้แย้งนั้นคุ้มค่ากับการแทรก symlink ที่มีศักยภาพ
สำหรับกรณีการใช้งานที่เข้มงวดซึ่งเรียกร้องให้กำจัด symlink ที่ซ้ำซ้อนzsh
ตัวแปรเฉพาะนี้ทำได้โดยใช้ builtins ที่มีประสิทธิภาพแทนที่จะใช้ส้อมที่ไม่มีประสิทธิภาพ:
+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
}
สังเกตการ*":${dirname:A}:"*
แทนที่*":${dirname}:"*
ของต้นฉบับ :A
เป็นมหัศจรรย์zsh
-ism เศร้าขาดภายใต้เปลือกหอยอื่น ๆ ส่วนใหญ่ - bash
รวมทั้ง อ้างถึงman zshexpn
:
ตอบ : เปลี่ยนชื่อไฟล์ให้เป็นพา ธ สัมบูรณ์ตามที่a
ตัวดัดแปลงทำแล้วส่งผลลัพธ์ผ่านrealpath(3)
ฟังก์ชั่นไลบรารีเพื่อแก้ไขลิงก์สัญลักษณ์ หมายเหตุ: สำหรับระบบที่ไม่มีrealpath(3)
ฟังก์ชันไลบรารีลิงก์สัญลักษณ์จะไม่ได้รับการแก้ไขดังนั้นในระบบเหล่านั้นa
และA
เทียบเท่า
ไม่มีคำถามเพิ่มเติม
ไม่เป็นไร สนุกกับการปอกเปลือกอย่างปลอดภัย ตอนนี้คุณสมควรได้รับมัน