如何在Shell脚本中运行别名?


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作为命令编写名为的Shell脚本文件。给我的Shell脚本适当的权限(使用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'
Nitin Venkatesh 2012年

@nitstorm:无论是解决方案似乎工作...我仍然得到同样的错误之前
保罗

Answers:


74
  1. 在您的Shell脚本中,使用完整路径而不是别名。

  2. 在您的Shell脚本中,设置变量,不同的语法

    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,前三者中的一个会更好。


15
第4点不起作用,除非您shopt -s expand_aliases在同一脚本中使用。
enzotib 2012年

您的建议2)有效,但是我希望能够在多个shell脚本中使用相同的命令,而不必编写第一行petsc =“ ...”。有没有办法做到这一点?
保罗

1
@enzotib-谢谢,我在答复中补充了这一点。
Panther

1
在第2点中,您没有设置别名而是设置了变量。
pabouk 2014年

1
OP并未要求它,但与问题标题有关:Point 2不适用于包含的命令|。在这里,使用shopt -s expand_aliases&本地别名,例如alias myalias='echo abc|rev'-使用前需要换行(请参阅中的ALIASES man bash)。要点4:源文件可能会阻止非交互式执行,即在脚本中。尽早查找exitreturn,例如[ -z "$PS1" ] && return(检查是否未设置主提示以指示非交互式shell)或可能存在iin 的检查$-$-包含shell选项,i表示交互式)。请参阅参考资料man bash
有效

60

不赞成使用别名,而希望使用Shell函数。从bash手册页:

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

要创建一个函数并将其导出到子shell,请将以下内容放入您的~/.bashrc

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

然后,您可以从脚本中自由调用命令。


几乎可以正常工作...唯一的问题是我需要能够将不同的标志传递给可执行文件“ mpiexec” ...例如,我需要能够使用以下命令执行类似“ petsc -n 40 myexecutable”的操作别名“ petsc”
保罗

4
@Paul:我添加"$@"只是为了处理参数。
enzotib 2012年

12

Shell函数和别名仅限于Shell,在已执行的Shell脚本中不起作用。您的情况的替代方法:

  • (如果您不想使用mpiexec代替petsc)将其添加$HOME/petsc-3.2-p6/petsc-arch/binPATH变量中。这可以通过编辑~/.profile和附加来完成:

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

    重新登录以应用这些更改

  • 创建目录~/bin

    • 创建一个petsc包含以下内容的包装器脚本:

      #!/bin/sh
      exec ~/petsc-3.2-p6/petsc-arch/bin/mpiexec "$@"
    • 如果程序允许,您可以跳过shellscript并使用以下命令进行符号链接:

      ln -s ~/petsc-3.2-p6/petsc-arch/bin/mpiexec ~/bin/petsc

9

在bash 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`" \;

完全不赞成使用别名,而希望使用shell函数,这个答案是唯一应该接受的答案。甚至旧的Debian 8都有bash的版本4,因此,这${BASH_ALIASES[alias]}是一个不错的选择。否则,我必须编辑.bash_aliases的许多行以应用其他内容。谢谢。
erm3nda

7

您可以使用-i标志强制bash将脚本作为交互式shell执行。这将告诉您的.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).

因此,对于那些希望在shell脚本中使用实际别名而不是替代别名的人,此问题的真正答案是:

#!/bin/bash

shopt -s expand_aliases

alias foo=bar

foo whatever

至于为什么要这样做:由于异常情况,我需要欺骗Dockerfile使其认为是Shell脚本。


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用于功能。


我喜欢这种解决方案,稍后再尝试
Greenonline 2015年

2
  1. 在shell脚本中使用别名。
  2. 在当前的交互式外壳程序中获取脚本而不是执行脚本。

因此,如果您script.sh的命令包含一个使用别名的文件,只需键入:

source script.sh

@DavidFoerster 此方法可以正常工作。使用.sourcebuiiltin 编写脚本会导致当前 shell执行其中的所有命令。如果别名扩展会在运行该shell .或在其中source运行的shell中发生,则会发生。但是,重要的是要认识到此方法仅在某些时候有用,因为通常一个人需要或想要在自己的Shell中使用自己的环境执行脚本。旨在以常规方式执行的Shell脚本通常不应取而代之-它们通常无法正常工作。
伊利亚·卡根

@EliahKagan:谢谢。现在,我明白了答案的含义。我将添加一个解释。
David Foerster,2017年

1

(编辑:删除了函数,因为我误读了mpiexec的调用。)

如果您所需要做的只是减少输入,为什么不将文件夹放在$ PATH中呢?还是从$ PATH中的某个文件夹建立指向mpiexec的符号链接?或者(我的最爱)将别名放在您从调用脚本中获取的脚本中?


1
我之所以不能将其放入$ PATH是因为我在$ PATH的另一个目录中有另一个“ mpiexec”文件。如果我将路径添加到这个新的“ mpiexec”中,则可能会尝试同时执行它们……不是吗?
保罗

1
无法理解为什么不简单使用"$@"
enzotib 2012年

2
Paul,它将尝试执行PATH中第一个而不是两者都执行的命令。
锤击

enzotib,嗯,我误解了mpiexec的调用方式,我认为它需要所有的args作为一个。将编辑我的答案:)
默默对待
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.