0
~$ bash --version
GNU bash, version 5.1.12(1)-release (x86_64-pc-linux-gnu)
~$ alias bab=python
~$ $(echo bab)
bash: bab: command not found

I'd expect bab to be turned to "python", but it seems it's not.

~$ $(echo alias)
alias bab='python'
alias ls='ls --color=auto'
~$ bab
Python 3.10.1 (main, Dec 11 2021, 17:22:55) [GCC 11.1.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 

The alias is recognized though, and works outside the interpolation. Why won't it work inside the interpolation?

eval works:

~$ eval $(bab)
Python 3.10.1 (main, Dec 11 2021, 17:22:55) [GCC 11.1.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 

I still wonder why

Kusalananda
  • 320,670
  • 36
  • 633
  • 936
Nitz
  • 143
  • 6
  • 2
    What do you mean by "works"? With `eval $(bab)` you would evaluate the _output_ of `bab`. Yes, it runs `python`, but that's _before_ it gets to `eval`. What is it that you are trying to achieve? – Kusalananda Jan 20 '22 at 16:32
  • 1
    `eval $(bab)` isn't doing what you think it's doing - you're seeing the `bab` alias running python. When that's completed the results will get passed to `eval`. You can see this by running a command in the `python` session such as `print("date\n")` – roaima Jan 20 '22 at 16:33
  • I reopened. This Q is not a duplicate of [this](https://unix.stackexchange.com/questions/1496/why-doesnt-my-bash-script-recognize-aliases). – glenn jackman Jan 20 '22 at 16:49
  • though `$(echo xyz)` in particular is pretty much useless, same as `echo $(zyx)`. But I assume you actually have some other expansion there. – ilkkachu Jan 20 '22 at 17:04
  • If you do `eval $(bab)`, or equally, `eval $(python)`, and try e.g. `print("hello")` in the interpreter, you'll see the output doesn't appear on the screen. Instead, when you exit the interpreter, Bash will complain about not finding the command `hello`... When starting the python interpreter in a command substitution, it's output is captured by the shell. It just prints the command line to the terminal, bypass the command substitution. You probably don't want that. Something like `var=$(python script.py)` would make more sense, of course. – ilkkachu Jan 20 '22 at 17:08
  • Also note that using `$(anything)` would not just run `anything`, it would expand the output of that command, split the output on the characters in `$IFS`, and apply filename globbing on the resulting strings. Then it would treat the first word as a command. It's unclear why you are attempting to use this syntax. – Kusalananda Jan 20 '22 at 17:35
  • @glennjackman how do I put in a vote for a suggested dup instead of wielding a hammer? – roaima Jan 20 '22 at 17:55
  • The tag gold badge comes with surprising powers sometimes. Perhaps just a comment? – glenn jackman Jan 20 '22 at 23:59
  • It's because $() starts a subshell without the alias of the parent shell. – Alexander Jan 28 '22 at 18:37

2 Answers2

3

Aliases get expanded before command substitution, documented in 3.1.1 Shell Operation. The "bab" that gets executed after $(echo bab) will not be handled as an alias.

Try using a function instead:

unalias bab
bab() { python "$@"; }
$(echo bab)       # launches a python shell
glenn jackman
  • 84,176
  • 15
  • 116
  • 168
1

From man bash

Aliases allow a string to be substituted for a word when it is used as the first word of a simple command.

AlexD
  • 1,088
  • 1
  • 10
  • 14