[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Exporting functions does not expand aliases in subshells
From: |
Kerin Millar |
Subject: |
Re: Exporting functions does not expand aliases in subshells |
Date: |
Thu, 11 Apr 2024 15:54:21 +0100 |
User-agent: |
Cyrus-JMAP/3.11.0-alpha0-379-gabd37849b7-fm-20240408.001-gabd37849 |
On Thu, 11 Apr 2024, at 10:05 AM, Philipp Lengauer wrote:
> Configuration Information [Automatically generated, do not change]:
> Machine: x86_64
> OS: linux-gnu
> Compiler: gcc
> Compilation CFLAGS: -g -O2 -flto=auto -ffat-lto-objects -flto=auto
> -ffat-lto-objects -fstack-protector-strong -Wformat -Werror=format-security
> -Wall
> uname output: Linux TAG009442498805 5.15.0-102-generic #112-Ubuntu SMP Tue
> Mar 5 16:50:32 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
> Machine Type: x86_64-pc-linux-gnu
>
> Bash Version: 5.1
> Patch Level: 16
> Release Status: release
>
> Description:
>
> When defining aliases and then exporting a function uses these aliases, the
> exported function body has the aliases expanded. This makes sense because
> we cannot be sure the same aliases exist in the child process where the
> exported function will eventually be used. However, when using subshells in
> the child process, the aliases are not expanded. This is unexpected
> behavior and potentially breaks the function.
>
> Repeat-By:
>
> # this is a minimal example showing where it works and where it doesnt work
> alias echo='echo PREFIX'
> echo hello world
> # prints "PREFIX hello world" => OK
There, the alias is expanded because you are in an interactive shell - where
the expand_aliases shell option is already enabled - and because it is the
"first word of a simple command".
> foo() { echo "hello world"; }
Likewise. Further, the alias is expanded at the time of the function's
declaration.
$ declare -f foo
foo ()
{
echo PREFIX "hello world"
}
> export -f foo
> bash -c 'foo'
> # prints "PREFIX hello world" => OK
>
> foo() { output="$(echo "hello world")"; printf '%s\n' "$output"; }
> export -f 'foo'
> # prints "hello world" => NOT OK (PREFIX missing)
There, the alias does not end up being expanded ...
$ declare -f foo
foo ()
{
output="$(echo "hello world")";
printf '%s\n' "$output"
}
Given that aliases cannot be exported by way of the environment as functions
can be, it ends up not working as you had anticipated. Even were it the case
that they could be, you would still have needed to enable expand_aliases in the
non-interactive shell.
Notwithstanding, I tried declaring the same function in an interactive instance
of dash and found that the alias within the command substitution does end up
being expanded, which is in stark contrast to the behaviour of bash.
$ ps -o comm= -p "$$"
dash
$ alias echo='echo PREFIX'
$ foo() { output="$(echo "hello world")"; printf '%s\n' "$output"; }
$ unalias echo
$ echo ok
ok
$ foo
PREFIX hello world
The behaviour of dash seems more logical to me, though I am uncertain as to
which shell is in the right.
--
Kerin Millar