Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS: -g -O2 -Werror=implicit-function-declaration 
-fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -flto=auto 
-ffat-lto-objects -fstack-protector-strong -fstack-clash-protection -Wformat 
-Werror=format-security -fcf-protection -Wall
uname output: Linux sal 6.11.0-13-generic #14-Ubuntu SMP PREEMPT_DYNAMIC Sat 
Nov 30 23:51:51 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
Machine Type: x86_64-pc-linux-gnu

Bash Version: 5.2
Patch Level: 32
Release Status: release

Description:
        A literal ~ or other tilde-prefix at the beginning of an
        element of $PATH is expanded when a command is executed
    from the bash prompt.  This is undocumented and inconsistent with
        the behavior of other commands that can execute commands.

    This expansion doesn't happen when bash is invoked as "/bin/sh"
    (which is a symlink to bash on some systems).

    The "Tilde Expansion" section of the bash manual does talk about
    using '~' when setting $PATH, but that applies only when setting
    it, not when using a $PATH containing literal '~' characters.

    A user who doesn't realize that, for example, "$HOME/bin" is
    expanded in double quotes but "~/bin" is not might end up with
    a $PATH setting that allows direct execution of some commands
    from the bash prompt, but those same commands can't be found by
    other tools.

    I haven't run into this issue myself.  This bug report is the
    result of a recent discussion in comp.unix.shell.

Repeat-By:
    Run this script:
    ```
    #!/bin/bash

    verbosely() {
        echo "\$ $*"
        "$@" || echo exit $?
    }

    export PATH='~/bin:/usr/bin:/bin'
    echo "PATH=$PATH"
    echo "HOME=$HOME"

    verbosely type fnord
    verbosely fnord             # This works (and arguably shouldn't)

    cat >run-fnord.c <<EOF
    #include <stdlib.h>
    int main(void) { system("fnord"); }
    EOF
    verbosely cat run-fnord.c
    verbosely gcc run-fnord.c -o run-fnord
    verbosely ./run-fnord       # This doesn't work
    ```

    The output on my system is:
    ```
    PATH=~/bin:/usr/bin:/bin
    HOME=/home/kst
    $ type fnord
    fnord is /home/kst/bin/fnord
    $ fnord
    This is fnord
    $ cat run-fnord.c
    #include <stdlib.h>
    int main(void) { system("fnord"); }
    $ gcc run-fnord.c -o run-fnord
    $ ./run-fnord
    sh: 1: fnord: not found
    ```

Fix:
    I haven't looked at the source code that implements this.
    I suggest documenting this feature in the next release and marking
    it as obsolescent, and then removing it in a later release.
    There could be existing code that depends on it -- which I
    suppose argues against removing it at all.  The documentation
    should at least mention that the expansion occurs and discuss
    the inconsistent treatment of $PATH by bash vs. other tools.

Reply via email to