bug-bash
[Top][All Lists]
Advanced

[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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]