sharkdp / fd

A simple, fast and user-friendly alternative to 'find'
Apache License 2.0
33.61k stars 803 forks source link

On Windows, find executables the same way the shell normally does. #1564

Open trytriangles opened 4 months ago

trytriangles commented 4 months ago

On Windows, if you have hello.py on your PATH and Python files designated as executable, you can it from the shell directly with and without its file extension:

$ hello world
Hello, world!

$ hello.py Rusty
Hello, Rusty!

It doesn't work in fd, however:

$ fd --exec hello
[fd error]: Command not found: hello

$ fd --exec hello.py
[fd error]: Problem while executing command: %1 is not a valid Win32 application.

I propose that on Windows fd's --exec be modified to find and execute programs the same way the regular shell does. This seems like the more expected and desirable behavior.

It can also avoid some potentially destructive situations when two programs of identical name exist, which can be common when things like Busybox are installed. Many shims are implemented as .ps1, .cmd, .bat or .ps1 files and users may find themselves executing unexpected things (e.g. I found that fd --exec ln gets me a shim to mklink, which takes _(linkname, target), when ln on its own gets me coreutils ln, which takes _(target, linkname).

I half-implemented this before reading the contributing guidelines and seeing the suggestion to open an issue before making a pull request, so here I am. There are two questions and concerns I'd have:

The registry keys associated with it have been there unchanged for at least 27 years so OS versions shouldn't be an issue.

tavianator commented 4 months ago
  • Doing this involves reading one to two values from the registry. If implemented, would it be preferable to do this using one of the pre-existing crates for registry interaction (adding an OS-specific dependency) or with a foreign-function call to the Windows API (adding an unsafe block)?

Ideally we would use a crate that does this for us, since the maintainers of that crate probably have more Windows expertise than we do.

But also, which registry keys are you talking about? I thought that the implicit executable extensions came from the PATHEXT environment variable.

Take this with a grain of salt because I haven't used Windows in many years, but I expect the ideal algorithm is something like this:

I can think of two complications: