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.