In article <
vn0bpf$29qe6$1@dont-email.me>,
Janis Papanagnou <janis_papanagnou+
ng@hotmail.com> wrote:
On 24.01.2025 14:46, Dan Cross wrote:
In article <vmu94j$1q2lp$1@dont-email.me>,
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
>
Bash behaves strange here; 'which' doesn't find the executable but
nonetheless bash executes it, shows its output?
Bash doesn't behave strangely here at all. Outside of its POSIX
mode, it's free to implement whatever behavior it likes with
respect to `~` expansion, and this is the behavior the author
has chosen.
But, critically, that does not mean that the programs _that it
invokes_ have to do the same. So while `bash` can perform `~`
expansion on the components of $PATH when it's searching for a
program to execute, one shouldn't be surprised if other programs
don't do the same thing.
>
As I see it, Bash does the same correct assignment to PATH in
case the tilde-expression is quoted or unquoted; here there's
no difference.
Bash demonstrably does not assign the same thing to $PATH when
the `~` is quoted or escaped versus unquoted/unescaped:
```
: term; exec bash
: term; PATH="~/bin:/bin:/usr/bin"
: term; echo $PATH
~/bin:/bin:/usr/bin
: term; PATH=~/bin:/bin:/usr/bin
: term; echo $PATH
/home/cross/bin:/bin:/usr/bin
: term;
```
Note that in the first form, the literal `~` character is in
$PATH, while in the second it has been expanded, and the result
is a pathname relative to my home directory.
Quoted or escaped it's a literal tilde in PATH,
unquoted it's an expanded tilde-expression. (As in all those
shells; bash, ksh, zsh, dash, sh.)
Yes, is what was shown.
As was pointed out, `which` is not built into the shell, and
therefore, not obligated to follow `bash`'s expansion rules.
>
And this (at least) seems to be the source of an inconsistency;
'which' is also in other shells not a built-in. But all other
shells I tested (ksh, zsh, dash, sh) handle it consistently;
If it's not built into those shells, then those shells don't
"handle" `which` in any meaningful way, other than exec'ing it
as they would any other program.
But `which` was just an example of a program that's not built
into the shell that inspects $PATH, which it inherited from the
shell that invoked it.
The interesting point of the example was to show that, as it
goes to run a program, `bash` will interpret each component of
`$PATH` and perform `~` expansion, but since it doesn't modify
`$PATH` when it does so, the programs that it invokes (and that
inherit `$PATH` from it) may not find programs that `bash` does
if they use execlp/execvp/etc, or even just inspect $PATH
directly.
if 'which' ("/usr/bin/which") detects no program [in PATH] it
should not execute some program. Other shells do that correctly.
Why do you say this? As I wrote earlier, nothing prevents
`bash` from treating $PATH however it likes outside of its POSIX
mode, and its behavior is entirely correct according to the
rules by which it does things. If other shells do things
differently, then that's their behavior; bash need not be bound
by it.
I've changed the above test frame to remove some unnecessary parts
to eliminate distracting complexity. The output for three shells:
Sorry, I think this cuts too much: the point was to show how the
different shells handle `~` in different contexts; the actual
strings that are in `$PATH` are important to show.
>
The actual strings and their handling WRT PATH is actually the
same in all these shells!
No it's not; that was the point.
Those test-cases have hidden the real problem,
That's the thing; there is no "problem." There are some
differences between how shells behave, but they're different
programs, so why is that bad?
The settings PATH=~/bin and PATH="~/bin" respectively shall
result in the same behavior across shells when searching for
programs; in the first case looking into "/home/someuser/bin/"
and in the second case looking into "./~/bin/" (i.e. a path
component with a local directory named "~").
I don't see any reason why that _must_ be true. Any given shell
is free to interpret $PATH any way it choses, or even use a
variable named something other than `PATH` for the search path.
For example, the `rc` shell used on 10th Edition Research Unix
and Plan 9 doesn't used `$path` (lower-case) to find programs.
It appears as if Bash invokes a tilde-expansion twice(!); once
[if unquoted] when the assignment happens, and another time
when the path-search is actually done.
Yes. That's precisely what I was showing.
Both of our test-cases
indicated that Bash seems to tilde-expand a PATH variable value
a second time;
I fail to see where this is being done a "second time": it seems
more likly that `bash` doesn't make any special note of the `~`
in `PATH="~/bin:whatever"` until it actuall goes to run a
program.
so while 'which' (as other shells and programs)
will not find any executable in "./~/bin/" (which would be the
correct interpretation of a quoted "~/bin") Bash does.
You seem to have invented a definition of "correct" here and are
pursuing it aggressively, but that is just one definition from
a large set of such definitions; there's no reason to assume the
behavior you expect here is any more correct than what `bash`
does.
That inconsistency - and deviating from all the other shells -,
Careful: "all other shells" is a pretty big net, and it wouldn't
surprise me at all if this broke down if you expanded the set of
things you were looking at. If you really want to twist your
nogging, have a look at what `csh` does, for example.
if not a bug, looks like a Bad Design Idea if it's been done
deliberately. - YMMV.
It's obviously being done deliberately, and is easy to find in
the source code:
https://git.savannah.gnu.org/cgit/bash.git/tree/findcmd.c#n533You may consider it bad design, and you're well within your
rights to do so, but opinions on that vary, and it doesn't mean
yours is correct.
- Dan C.