Как запустить псевдоним в сценарии оболочки?

101

У меня есть исполняемый файл mpiexec, полный путь которого ~/petsc-3.2-p6/petsc-arch/bin/mpiexec. Поскольку я хочу выполнить эту команду в разных каталогах (без необходимости повторного ввода всего пути), я установил псевдоним в своем домашнем .bashrcфайле:

alias petsc="~/petsc-3.2-p6/petsc-arch/bin/mpiexec"  

что позволяет мне mpiexecлегко выполнить этот файл в командной строке, набрав:

petsc myexecutable

Я попытался написать файл сценария оболочки с именем script, используя мой новый псевдоним petscв качестве команды. После предоставления моему сценарию оболочки соответствующих разрешений (используя chmod) я попытался запустить сценарий. Тем не менее, это дало мне следующую ошибку:

./script: line 1: petsc: command not found

Я знаю, что могу просто написать полный путь к mpiexecфайлу, но каждый раз, когда я хочу написать новый скрипт, сложно писать полный путь. Есть ли способ, которым я могу использовать свой псевдоним petscв файле сценария? Есть ли способ, которым я могу отредактировать свой .bashrcили .bash_profileсделать это?

Павел
источник
Как насчет добавления псевдонима .bash_aliases? Также как насчет наложения абсолютного пути вместо относительного пути, какalias petsc='/home/user/petsc-3.2-p6/petsc-arch/bin/mpiexec'
Нитин Венкатеш
@nitstorm: ни одно из решений, похоже, не работает ... Я все еще получаю ту же ошибку, что и раньше
Пол
Связано: unix.stackexchange.com/questions/1496/…
АликЭльзин-килака

Ответы:

74
  1. В вашем сценарии оболочки используйте полный путь, а не псевдоним.

  2. В вашем сценарии оболочки установите переменную, другой синтаксис

    petsc='/home/your_user/petsc-3.2-p6/petsc-arch/bin/mpiexec'
    
    $petsc myexecutable
    
  3. Используйте функцию в вашем скрипте. Наверное, лучше, если petscэто сложно

    function petsc () {
        command 1
        command 2
    }
    
    petsc myexecutable
    
  4. Источник ваши псевдонимы

    shopt -s expand_aliases
    source /home/your_user/.bashrc
    

Вы, вероятно, не хотите, чтобы ваш источник .bashrc, поэтому, IMO, один из первых 3 будет лучше.

пантера
источник
16
Пункт 4 не работает, если вы не используете shopt -s expand_aliasesв том же сценарии.
энзотиб
Ваше предложение 2) работает, но я хочу иметь возможность использовать одну и ту же команду в нескольких сценариях оболочки без необходимости писать первую строку petsc = "...". Есть ли способ сделать это?
Пол
1
@enzotib - спасибо, я добавил это к своему ответу.
Пантера
1
В пункте 2 вы устанавливаете не псевдоним, а переменную.
Пабук
1
Не запрашивается OP, но относится к заголовку вопроса: пункт 2 не будет работать с командами, содержащими |. Здесь используйте shopt -s expand_aliases& локальный псевдоним, например, alias myalias='echo abc|rev'- требует перенос строки перед использованием (см. Псевдонимы в man bash). Пункт 4: исходный файл может предотвратить неинтерактивное выполнение, т. Е. В сценарии. Ищите рано exitили return, например [ -z "$PS1" ] && return(проверяет, не установлено ли основное приглашение, указывающее на неинтерактивную оболочку) или может быть проверка на iвход $-( $-содержит параметры оболочки, iозначает интерактивную). Смотрите man bashдля этих переменных.
действует
62

Псевдонимы устарели в пользу функций оболочки. Со bashстраницы руководства:

For almost every purpose, aliases are superseded by shell functions.

Чтобы создать функцию и экспортировать ее в подоболочки, добавьте в свой файл следующее ~/.bashrc:

petsc() {
    ~/petsc-3.2-p6/petsc-arch/bin/mpiexec "$@"
}
export -f petsc

Тогда вы можете свободно вызывать свою команду из ваших скриптов.

enzotib
источник
Это почти работает ... единственная проблема заключается в том, что мне нужно иметь возможность передавать различные флаги исполняемому файлу "mpiexec" ... Например, мне нужно иметь возможность выполнять что-то вроде "petsc -n 40 myexecutable" с псевдоним "petsc"
Пол
4
@Paul: я добавил "$@"только для обработки аргументов.
энзотиб
12

Функции оболочки и псевдонимы ограничены оболочкой и не работают в исполняемых скриптах оболочки. Альтернативы для вашего случая:

  • (если вы не хотите использовать mpiexecвместо petsc) Добавить $HOME/petsc-3.2-p6/petsc-arch/binк вашей PATHпеременной. Это может быть сделано путем редактирования ~/.profileи добавления:

    PATH="$HOME/petsc-3.2-p6/petsc-arch/bin:$PATH"

    Повторно войдите, чтобы применить эти изменения

  • Создать каталог ~/binи

    • сделать скрипт-оболочку с именем, petscсодержащим:

      #!/bin/sh
      exec ~/petsc-3.2-p6/petsc-arch/bin/mpiexec "$@"
      
    • если программа это позволяет, вы можете пропустить скрипт и создать символическую ссылку, используя команду:

      ln -s ~/petsc-3.2-p6/petsc-arch/bin/mpiexec ~/bin/petsc
Lekensteyn
источник
9

В Баш 4 вы можете использовать специальную переменную: $BASH_ALIASES.

Например:

$ alias foo="echo test"
$ echo ${BASH_ALIASES[foo]}
echo test
$ echo `${BASH_ALIASES[foo]}` bar
test bar

В качестве альтернативы определите как переменную, затем используйте подстановку команды или eval.

Так, например, вместо определения псевдонима, такого как:

alias foo="echo test"

определить это как:

foo="echo test"

вместо. Затем выполните это:

find . -type f -exec sh -c "eval $foo" \;

или же:

find . -type f -exec sh -c "echo `$foo`" \;
kenorb
источник
Хотя псевдонимы не рекомендуются в пользу функций оболочки, этот ответ является единственным, который следует принять. Даже старый Debian 8 имеет версию 4 bash, так что ${BASH_ALIASES[alias]}это хороший вариант. В противном случае мне пришлось редактировать много строк моего .bash_aliases, чтобы применить другие вещи. Спасибо.
erm3nda
8

Вы можете заставить bash выполнить ваш скрипт в виде интерактивной оболочки с флагом -i. Это скажет вашему файлу .bashrc определить псевдонимы и другие функции.

Пример:

~ $ grep ll .bashrc
alias ll='ls -lah'
~ $ cat script.sh 
#!/bin/sh

ll
~ $ bash script.sh 
script.sh: line 3: ll: command not found
~ $ bash -i script.sh
..directory contents..

Больше информации:

$ man bash
Амадо Мартинес
источник
2
.bashrcтакже читается во время неинтерактивного выполнения команды SSH (поэтому вверху есть проверка на интерактивность)
muru
6
ALIASES
   ...
   Aliases are not expanded when the shell is not interactive, unless the expand_aliases shell option is set using shopt (see the description of shopt under SHELL BUILTIN COMMANDS
   below).

Таким образом, реальный ответ на этот вопрос для тех, кто хочет использовать реальные псевдонимы в сценариях оболочки вместо их альтернатив:

#!/bin/bash

shopt -s expand_aliases

alias foo=bar

foo whatever

Что касается того, почему я хотел бы сделать это: из-за необычных обстоятельств мне нужно обмануть Dockerfile, думая, что это скрипт оболочки

Сбросить аккаунт
источник
4
  1. В .bash_aliases:

    petsc {
    ~/petsc-3.2-p6/petsc-arch/bin/mpiexec "$@"
    }
    

    Или вставьте функцию .bashrc. Обычно .bashrcтолько в конфиге bashхранятся настройки .

  2. В терминале: source .bash_aliases

  3. Назови это: petsc arg(s)

Преимущество: Вам не нужно export -f petscв .bash_aliases. Псевдонимы устарели, но использование .bash_aliasesдля функций в порядке.

Timo
источник
Мне нравится это решение, я попробую его позже
Greenonline
2
  1. Используйте ваши псевдонимы в вашем сценарии оболочки.
  2. Поставьте ваш скрипт в вашу текущую интерактивную оболочку, а не выполняйте его.

Поэтому, если у вас есть файл, вызываемый script.shвашими командами, которые включают использование псевдонимов, просто введите:

source script.sh
Гордон Эрлебахер
источник
@DavidFoerster Этот метод работает отлично. Получение сценария с помощью .или sourcebuiiltin заставляет текущую оболочку выполнять все команды в нем. Если расширение псевдонима произойдет в оболочке, в которой .или sourceвыполняется, это происходит. Тем не менее, важно понимать, что этот метод полезен только иногда, потому что часто нужно или нужно выполнить скрипт в его собственной оболочке, со своей собственной средой. Сценарии оболочки, написанные с намерением выполнить обычным способом, обычно не следует использовать вместо этого - они часто не будут работать правильно.
Элия ​​Каган
@EliahKagan: Спасибо. Теперь я понимаю, что должен означать ответ. Я добавлю объяснение.
Дэвид Фёрстер
1

(РЕДАКТИРОВАТЬ: удалены функции, так как я неправильно прочитал вызов mpiexec.)

Если единственное, что вам нужно, это меньше печатать, почему бы вам просто не поместить папку в $ PATH? Или сделать символическую ссылку на mpiexec из какой-либо папки в $ PATH? Или (мой любимый) поместить псевдоним в сценарий, который вы используете в вызывающем сценарии?

unhammer
источник
1
Причина, по которой я не могу поместить его в свой $ PATH, заключается в том, что у меня есть другой файл 'mpiexec' в другом каталоге, который уже есть в моем $ PATH. Если я добавлю путь к этому новому mpiexec, он, вероятно, попытается выполнить их оба ... не так ли?
Пол
1
Не могу понять, почему не просто использовать "$@".
энзотиб
2
Пол, он попытается выполнить тот, который первый в ПУТИ, а не оба.
unhammer
Энзотиб, ах, я неправильно понял, как называется mpiexec, я думал, что нужны все аргументы как один.
Отредактирую