Чому мій сценарій Bash не розпізнає псевдоніми?


216

У моєму ~/.bashrcфайлі є два визначення:

  1. commandA, що є псевдонімом більш тривалого шляху
  2. commandB, який є псевдонімом сценарію Bash

Я хочу обробити один і той же файл із цими двома командами, тому я написав такий сценарій Bash:


#!/bin/bash

for file in "$@"
    do
    commandA $file
    commandB $file
done

Навіть після виходу з сеансу та входу в систему, Bash command not foundвикликає помилки для обох команд, коли я запускаю цей сценарій.

Що я роблю неправильно?


10
До речі, не потрібно входити та виходити, щоб визнати псевдонім. Вам потрібно просто зробити source ~/.bashrc.
thepang

У моєму випадку до мене було віддалено підключено агент SSH, після додавання псевдоніма, коли я закрив агент SSH і знову підключився, він почав працювати.
дав

Псевдонім - це спосіб скорочення команди. (Вони використовуються лише в інтерактивних оболонках, а не в сценаріях - це одна з небагатьох відмінностей між сценарієм та інтерактивною оболонкою.)
Кріс Руф

Відповіді:


117

Перш за все, як сказав ddeimeke, псевдоніми за замовчуванням не розширюються в неінтерактивних оболонках.

По-друге, .bashrcне читається неінтерактивними оболонками, якщо не встановити BASH_ENVзмінну середовища.

Але найголовніше: не робіть цього! Будь ласка? Одного разу ви перемістите цей сценарій кудись, де не встановлені необхідні псевдоніми, і він знову порушиться.

Замість цього встановіть і використовуйте змінні середовища як ярлики у вашому сценарії:

#!/bin/bash

CMDA=/path/to/gizmo
CMDB=/path/to/huzzah.sh

for file in "$@"
do
    $CMDA "$file"
    $CMDB "$file"
done

5
Це рішення не працює для звичайних aliasвипадків використання. Напр alias mv="mv -v --backup=numbered".
Evi1M4chine

@ Evi1M4chine: Так, це так. Принаймні після того, як я повернув Жиль непотрібне редагування. Але може бути краще використовувати іншу змінну для параметрів у будь-якому випадку.

1
Ах, зауважте, відсутність цитат навколо $CMDA/ $CMDB… Окрім того, що великі регістри зарезервовані для самої гри в bash, і вона справді працює, ця відсутність лапок робить мене дуже непросто ... Спасибі все одно.
Evi1M4chine

@ Evi1M4chine: А, що? 1. Я видалив цитати в останній редакції. 2. звідки ви берете "зарезервований для самого баш"? це було б перше, що я чув про це. 3. Якщо це робить вас неприємно, як ви ставитесь до використання bash в першу чергу? У будь-якому випадку, використовуйте окрему змінну для параметрів, як я вам сказав.

1
@alvas: припущення полягає в тому, що gizmoце не шлях, або є команда з такою ж назвою, але з більш високим пріоритетом. в іншому випадку ви можете просто встановити CMDAрівне gizmoмісце в першу чергу.

161

Якщо ви заглянете в баш-сторінку, ви знайдете:

Псевдоніми не розгортаються, коли оболонка не є інтерактивною, якщо не встановлено параметр shell_aliases оболонки за допомогою shopt (див. Опис прострілу в SHELL BUILTIN COMMANDS нижче).

Тому поставте

shopt -s expand_aliases

у вашому сценарії.

Переконайтеся, що ви джерело псевдоніму після встановлення цього сценарію.

shopt -s expand_aliases
source ~/.bash_aliases

7
Я розмістив це у своєму сценарії, але він все ще не працює. Та сама помилка.
Заїд

5
Додавання shopt -s expand_aliases source ~/.bash_aliasesпрацює для мене ідеально. Часто в .bashrc є така форма інтерактивного виявлення оболонки: # If not running interactively, don't do anything [ -z "$PS1" ] && return@Zaid, можливо, ви хочете перевірити це у файлі, який ви отримали.
Френк Шуберт

1
чудово! зберегли мої сценарії !! :) Настільки важко читати / шукати / переглядати інформацію та маніпуляції в терміналі, що я просто давно відмовився і пішов шукати в Інтернеті ...
Водолій Сила

2
Цікаво, shopt -s expand_aliasesщо не потрібно йти до визначення псевдоніма, але до використання псевдоніма. Додавання до @FrankSchubert: Інтерактивне виявлення оболонки також може бути здійснено, використовуючи $-параметри для оболонки, зокрема, iякщо оболонка інтерактивна.
діє

2
це не правильна відповідь ... Визначення псевдонімів у вашому сценарії не є відповіддю. Ви можете ~/.bash_aliasesзалежати від інших речей, які раніше завантажувались в інтерактивну оболонку ... Найближче, що я знайшов, - це змінити ваш хешбанг на #!/bin/bash -liЩе не ідеальний. В ідеалі слід використовувати функції, а не псевдоніми.
Стефанос Каланціс

44

Псевдоніми не можна експортувати, тому вони недоступні у скриптах оболонки, у яких вони не визначені. Іншими словами, якщо ви визначите їх у них, ~/.bashrcвони недоступні your_script.sh(якщо ви не вкажете джерело ~/.bashrcсценарію, що я б не рекомендував, але є способи зробити це правильно).

Однак функції можна експортувати та будуть доступні для скриптів оболонки, які виконуються із середовища, в якому вони визначені. Це можна зробити, помістивши це у свій bashrc:

foo ()
{
    відлуння "Привіт, світ!"
}
експорт -foo

Як говориться в посібнику Баша, "майже для будь-яких цілей функції оболонки є кращими перед псевдонімами".


1
Хоча це технічно не відповідає на питання, як ви говорите , ви можете просто замінити alias commandA=...з commandA() { ... }потім export commandAі ви отримаєте ідентичне поведінка на псевдонім. Тож це майже однакова альтернатива псевдонімів, наскільки я знаю, що чудово працює в сценаріях баш
Phylliida

Проблема тут полягає в тому, коли вам потрібен псевдонім, на який ви передаєте безліч цитованих варіантів. наприклад, як приклад, alias b=bashце легко зробити, b -c "echo test | grep test"що було б складно виконати у функціях.
Fmstrat

@Fmstrat: b () { bash "$@"; }тодіb -c "echo test | grep test"
Денніс Вільямсон


-5

Я іноді знайшов, що сценарій bash також не розпізнає експорт. Однак, змінивши його на

#!/bin/sh

працює для мене.


1
Ні, не вийшло ...
Хафіз Темурі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.