为什么我的 Bash 脚本不能识别别名?

Zai*_*aid 272 bash alias

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

  1. commandA,这是更长路径的别名
  2. commandB,这是 Bash 脚本的别名

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


#!/bin/bash

for file in "$@"
    do
    commandA $file
    commandB $file
done
Run Code Online (Sandbox Code Playgroud)

即使在退出会话并重新登录后,command not found当我运行此脚本时,Bash 仍会提示我输入两个命令的错误。

我究竟做错了什么?

dde*_*eke 214

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

当 shell 不是交互式时,别名不会扩展,除非使用 shopt 设置 expand_aliases shell 选项(请参阅下面的 SHELL BUILTIN COMMANDS 下的 shopt 描述)。

所以放一个

shopt -s expand_aliases
Run Code Online (Sandbox Code Playgroud)

在你的脚本中。

在您的脚本中设置此文件后,请确保获取您的别名文件。

shopt -s expand_aliases
source ~/.bash_aliases
Run Code Online (Sandbox Code Playgroud)

  • 我把它放在我的脚本中,但它仍然不起作用。同样的错误。 (13认同)
  • 添加`shopt -s expand_aliases source ~/.bash_aliases` 非常适合我。.bashrc 中通常有一种交互式 shell 检测形式,如下所示:`# 如果不是交互式运行,不要做任何事情 [ -z "$PS1" ] && return` @Zaid,也许你想在您获取的文件。 (7认同)
  • 这不是一个正确的答案......在脚本中获取别名不是答案。你的`~/.bash_aliases` 可能依赖于以前加载在交互式 shell 上的其他东西......我发现最接近的事情是将你的 hashbang 更改为 `#!/bin/bash -li` 仍然不完美。理想情况下,您应该使用函数而不是别名。 (4认同)
  • 奇怪的是,`shopt -s expand_aliases` 不必在别名定义之前,而是在别名使用之前。添加到@FrankSchubert:交互式外壳检测也可以使用`$-` 来完成,它包含外壳的选项,如果外壳是交互式的,则特别是`i`。 (3认同)
  • 唉,这不适用于 `bash -c`,例如 `bash -c "shopt -s Expand_aliases; source my-script.sh; some-alias`。仍然得到 `some-alias: command not find` (2认同)

小智 148

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

其次,.bashrc除非您设置了BASH_ENV环境变量,否则不会被非交互式 shell 读取。

但最重要的是:不要那样做!请?有一天你会将该脚本移动到没有设置必要别名的地方,它会再次中断。

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

#!/bin/bash

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

for file in "$@"
do
    $CMDA "$file"
    $CMDB "$file"
done
Run Code Online (Sandbox Code Playgroud)

  • 该解决方案不适用于通常的“别名”用例。例如`alias mv="mv -v --backup=numbered"`。 (7认同)

Den*_*son 58

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

但是,函数可以导出,并且可用于从定义它们的环境中运行的 shell 脚本。这可以通过将它放在你的 bashrc 中来完成:

富()
{
    回声“世界你好!”
}
导出 -f foo

正如 Bash 手册所说,“对于几乎所有用途,shell 函数都比别名更受欢迎。”

  • 虽然这在技术上不能回答这个问题,但正如您所说,您可以简单地将 `alias commandA=...` 替换为 `commandA() { ... }` 然后是 `export commandA`,并且您会得到与别名相同的行为。因此,据我所知,这几乎是别名的替代方案,在 bash 脚本中效果很好 (2认同)

小智 16

[cmd line] > bash -i [your script's file path]
Run Code Online (Sandbox Code Playgroud)

i是用于交互式并bash为您提供您的个人资料。


Ton*_*Nam 16

您也可以.在脚本之前使用。运行它作为:

. /path/to/your/script.sh
Run Code Online (Sandbox Code Playgroud)

您可以在 bash 脚本中检查此情况,如下所示:

if [[ $- == *i* ]]
then
    echo "running on interactive mode. aliases will work!"
fi
Run Code Online (Sandbox Code Playgroud)

  • 对于避免编辑脚本本身的解决方案(这就是为什么我们存在脚本以便可以在许多人之间共享),这真的很棒 (2认同)