Ось! 12-лінійна промислова потужність ... технічно функціональна оболонка з базовою та zsh-технологією, яка віддано любить ваш вибір ~/.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
мовчки приймають і, в основному, ігнорують відносні прізвища в більшості випадків, відносні дирікаменти з префіксом або, h
або t
(можливо, іншими недобрими персонажами) призводять до того, що вони ганебно понівечать семінарський шедевр ала Масакі Кобаяші 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}
дирижаблі в основному нешкідливі, вони також небажані, громіздкі, м'яко неефективні, перешкоджають налагодженню та сприяють зносу приводу - подібного роду відповідь. Незважаючи на те , що жорсткі диски у стилі 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}
дирікаменти в основному нешкідливі, вони також, як правило, небажані, громіздкі, м'яко неефективні, перешкоджають налагодженню та сприяють зносу приводу.
Ерго, дружелюбна автоматизація, як функція оболонки, визначена вище. Ми повинні врятувати себе від себе.
Але ... Чому "+ path.append ()"? Чому б не просто append_path ()?
Для disambiguity (наприклад, з зовнішніми командами в поточній ${PATH}
або всій системі функцій оболонки , визначених в іншому місці), що визначається користувач функція оболонки ідеально приставка або суфікс з унікальними підрядками , підтримуваних bash
і , zsh
але іншим чином заборонена для стандартних команд basenames - як, скажімо, +
.
Гей. Це працює. Не судіть мене.
Але ... Чому "+ path.append ()"? Чому б не "+ path.prepend ()"?
Оскільки приєднання до струму ${PATH}
є більш безпечним, ніж попередження струму ${PATH}
, всі речі рівні, якими вони ніколи не є. Перевизначення загальносистемних команд з конкретними для користувача командами може бути антисанітарним у кращому випадку та божевільним. Наприклад, під Linux, додатки нижче за течією зазвичай очікують варіантів команд GNU, а не спеціальні нестандартні похідні або альтернативи.
Однак, для цього абсолютно є дійсні випадки використання. Визначення еквівалентної +path.prepend()
функції тривіальне. Не враховує туманність, за його та її спільний розум:
+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
}
Але ... Чому б не Жиль?
Прийнята відповідь Жиля в іншому місці є вражаючо оптимальною в загальному випадку як "додаток агностичного ідентифікаційного оболонки" . У загальному випадку bash
і zsh
з НЕ небажаних симлінк, однак, втрати продуктивності потрібно зробити так засмучує на приготування овочевого пюре Gentoo в мені. Навіть за наявності небажаних символьних посилань, дискусійним є питання про те, чи варто роздрібнення однієї підзарядки на add_to_PATH()
аргумент потенційної вставки дублікатів символьних посилань .
Для випадків суворого використання, які вимагають усунення навіть дублікатів zsh
симпосилання , це специфічний варіант робить це за допомогою ефективних вбудованих, а не неефективних вил:
+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
жаль, відсутність у більшості інших оболонок - у тому числі bash
. Цитувати man zshexpn
:
A : Перетворіть ім'я файлу в абсолютний шлях, як це a
робить модифікатор, а потім передайте результат через функцію realpath(3)
бібліотеки для вирішення символічних посилань. Примітка. У системах, які не мають realpath(3)
бібліотечної функції, символьні посилання не вирішуються, тому на цих системах a
і A
є рівнозначними.
Ніяких додаткових питань.
Ласкаво просимо. Насолоджуйтесь безпечним обстрілом. Ви зараз на це заслужили.