在我的~/.bashrc文件中包含两个定义:



commandA,它是较长路径的别名。 Bash脚本

我想用这两个命令处理同一文件,所以我编写了以下Bash脚本:


#!/bin/bash

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


即使注销了会话并重新登录后,运行该脚本时,Bash也会提示我两个命令均出现commandB错误。

我在做什么错?

评论

顺便说一句,无需登录和注销即可识别别名。您只需要执行源〜/ .bashrc。

就我而言,我在关闭SSH代理并再次连接后开始添加别名后,通过SSH代理远程连接。

别名是一种缩短命令的方法。 (它们仅在交互式外壳中使用,而不在脚本中使用-这是脚本和交互式外壳之间的极少数差异之一。)

#1 楼

首先,正如ddeimeke所说,默认情况下,别名不会在非交互式shell中扩展。

其次,除非您设置.bashrc环境变量,否则非交互式shell不会读取BASH_ENV。 >
但最重要的是:不要那样做!请?有一天,您将把该脚本移到未设置必要别名的地方,它将再次中断。

在脚本中设置并使用变量作为快捷方式:

#!/bin/bash

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

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


评论


该解决方案不适用于通常的别名用例。例如。别名mv =“ mv -v --backup = numbered”。

– Evi1M4chine
16年4月23日在20:11

@ Evi1M4chine:是的。至少在我还原了Gilles不必要的编辑之后。但是无论如何,最好对参数使用不同的变量。

–user601
16年4月24日在15:50

嗯,请注意$ CMDA / $ CMDB周围缺少引号...除了在bash中为bash本身保留大写变量,而且确实有效之外,缺少引号让我真的很不舒服...还是谢谢。

– Evi1M4chine
16年4月30日在0:26

@ Evi1M4chine:嗯,什么? 1.我本人在最近的编辑中删除了引号。 2.您从何处获得“保留给bash本身”?这将是我第一次听说。 3.如果这让您感到不安,那么首先感觉如何使用bash?无论如何,请按照我告诉您的方式为选项使用单独的变量。

–user601
16年4月30日在17:46

@alvas:假定gizmo不在路径上,或者存在具有相同名称但具有更高优先级的命令。否则,您可以首先简单地将CMDA设置为纯Gizmo。

–user601
17-4-5在9:20



#2 楼

如果查看bash联机帮助页,则会发现:


如果交互式交互式
shell不扩展别名,除非设置了
expand_aliases shell选项
使用shopt(请参阅下面的SHELL BUILTIN COMMANDS下的
shopt的说明
)。 br />
在脚本中。

在脚本中设置别名后,请确保提供别名文件。

shopt -s expand_aliases


评论


我将其放在脚本中,但仍无法正常工作。同样的错误。

– Zaid
2010-09-2 10:29

添加shopt -s expand_aliases源〜/ .bash_aliases非常适合我。通常,.bashrc中有一种交互式外壳程序检测形式,如下所示:#如果未以交互方式运行,则不执行任何操作[-z“ $ PS1”] &&返回@Zaid,也许您想检查文件中的内容即可。来源。

–弗兰克·舒伯特(Frank Schubert)
13年4月4日在1:46



优秀的!保存了我的脚本! :)很难在终端上阅读/搜索/浏览信息和手册页,以至于我很久以前就放弃了,可以在互联网上搜索...

–水瓶座力量
2013年9月17日19:24在

奇怪的是,shopt -s expand_aliases不必在别名定义之前,而在使用别名之前。添加到@FrankSchubert:交互式shell检测也可以使用$-进行,该$包含shell的选项,特别是i(如果shell是交互式的)。

–有效
15年3月20日在14:12

这不是正确的答案...在脚本中添加别名不是答案。您的〜/ .bash_aliases可能取决于先前加载在交互式shell上的其他内容...我发现的最近的东西是将您的hashbang更改为#!/ bin / bash -li仍然不完美。理想情况下,您应该使用函数而不是别名。

– Steefanos Kalantzis
16-2-5在11:47



#3 楼

别名无法导出,因此在未定义别名的Shell脚本中不可用。换句话说,如果您在~/.bashrc中定义它们,则它们对your_script.sh不可用(除非您在脚本中提供~/.bashrc,我不建议这样做,但是有一些方法可以正确执行此操作)。

但是,可以导出函数,这些函数可用于在定义它们的环境中运行的Shell脚本。可以通过将其放在您的bashrc中来完成:

foo()
{
    echo "Hello World!"
}
export -f foo


正如Bash手册中所说:“几乎所有目的,shell函数都比别名更受青睐。” />

评论


虽然从技术上讲这还不能解决问题,但是正如您所说,您可以简单地将别名commandA = ...替换为commandA(){...},然后导出commandA,您将获得与别名相同的行为。因此,据我所知,这几乎是别名的替代选择,在bash脚本中效果很好

–菲利达
18年5月21日在18:35



这里的问题是,当您需要一个别名时,将许多引用的选项传递给它。例如,使用别名b = bash可以很容易地执行b -c“回声测试| grep测试”,而这在函数中是很难做到的。

– Fmstrat
19年8月13日在16:03

@Fmstrat:b(){bash“ $ @”;然后b -c“ echo test | grep test”

–丹尼斯·威廉姆森
19年8月13日在16:10

当需要在从另一个脚本获得功能的脚本中评估函数的内容时,这不能解决问题...

–明仁
20年1月29日在18:10

#4 楼

[cmd line] > bash -i [your script's file path]


i用于互动,并为您提供bash配置文件。

#5 楼

您可以在脚本之前使用.。将其运行为:
. /path/to/your/scrtip.sh

您可以在bash脚本中以以下方式检查此情况:
if [[ $- == *i* ]]
then
    echo "running on interactive mode. aliases will work!"
fi


#6 楼

我发现有时bash脚本也无法识别导出。但是,将其更改为

#!/bin/sh


对我有用。

评论


不,不是...

–哈菲兹·特姆里(Hafiz Temuri)
18年4月22日在17:12