A kinda relevant question.
I use Windows most of time. Like the author, I have bunch of CLI scripts (in Python mainly) which I put into my ~/bin/ equivalent.
After setting python.exe as the default program for `.py` extension, and adding `.py` to `%pathext%`, I can now run my ~/bin/hello.py script at any path by just type `hello`, which I use hundreds of time a day.
I now use Linux more and more (still a newbie) but I never get it to work similarly here.
Firstly, Linux seems to have no concept of "associated program", so you can never "just" call .py file, and let the shell to know to use python to execute it. Sure, you can chmod +x to the script, but then you have to add a shebang line directly to the script itself, which I always feel uncomfortable since it's hard-coded (what if in future I don't want to execute my .py script with `/usr/bin/python` but `/usr/bin/nohtyp`?).
Furthermore, I failed to find any way to omit `.py` part when calling my script.
Again, none of the above is to question the design of the Linux -- I know it comes with lots of advantages.
But I really, really just want to run `hello` to call a `hello.py` script that is in my $PATH.
Your example got me thinking about the difference between how the windows shell and Unix shell is designed. Seems like the windows shell knows about extensions, whereas the Unix shell does not
That’s an interesting feature for a shell to have. Thanks!
It's can be traced back to the roots of each OS. Windows has it's heritage in the land of DOS where files had an 8 character name with a 3 character extension and that extension carried meaning for the OS.
Linux being of Unix ancestry which had no such concept as a file extension. It was the responsibility of the application or kernel to discern what type a file was. Typically by the first few bytes of a file and handle it appropriately.
I personally am a fan of the Unix way but I can see why some might prefer the DOS convention.
Speaking of heritage... 8+3 goes back at least to DECSystem-10 on PDP-10s.
Everything goes back to the PDP-10 we are all using the incestuous off-spring of DEC.
Whether that is good or bad is left as an exercise to the reader.
A lot of it came from RSX11 features that got rolled into the PDP-10 OSes.
6+3 on DEC TOPS-10.
Might be you could use binfmt_misc for that.
https://www.kernel.org/doc/html/latest/admin-guide/binfmt-mi...
binfmt_misc is only useful for when a fileformat does not allow shebangs
Or if you don't want to use shebangs as mentioned.
Here is an article about using binfmt_misc to make .go files executable. I assume something similar could be done for python:
https://blog.cloudflare.com/using-go-as-a-scripting-language...
> then you have to add a shebang line directly to the script itself, which I always feel uncomfortable since it's hard-coded (what if in future I don't want to execute my .py script with `/usr/bin/python` but `/usr/bin/nohtyp`?)
> But I really, really just want to run `hello` to call a `hello.py` script that is in my $PATH.
On Linux I'd say the shebang is still the right tool for this. If you want a lightweight approach, just have a `my_python` symlink in your path, then your shebang can be `/usr/bin/env my_python` (or heck just `/foo/bar/baz/my_python`, /usr/bin/env is already an abstraction).
If you want a more principled approach, look at the `update-alternatives` tool, which provides this sort of abstraction in a more general way: https://linuxconfig.org/how-to-set-default-programs-using-up...
Isn't that path and the behavior of the binary defined by POSIX though? I thought it's as stable as you can get.
That's why it's usually recommended that you use /use/bin/env bash vs /bin/bash in the shebang, as the latter isn't defined by POSIX
I don't see anything about the path being defined. Certainly possible I missed it, though.
I'm not able to check right now but I vaguely recall that I've used a system in the past with env in a location other than /usr/bin.
Yes, env is an abstraction for the sake of portability, but if you're setting up custom indirections then portability probably isn't much of a concern.
It won’t directly help reach your goal, but it is semi hard-coded. The ‘correct’ (but see https://unix.stackexchange.com/a/29620 for some caveats) way to write a shebang line is
That will make it run the first python in your path.You could create a symlink called python to /usr/bin/nohtyp on your system in a directory that’s searched before /usr/bin (e.g. by adding ~/myCommandPreferences to the front of your PATH)
To be excruciatingly correct, we should specify python2 or python3, because they can't interop and probably never will.
I think at this point we can rest easy that python2 has finally been fully purged from default installs. Heck a few weeks ago I installed Kubuntu 24.04 base and there was no Python at all...
Debian stable doesn't have "python" anywhere on my PATH, for a good reason IMHO. Shebangs say "/usr/bin/env python3" or hardcode "/usr/bin/python3".
you're thinking too much, people have had that shebang for 20 years without any problems
I don't really understand why you're so adamant about this, either make a python "hello" script with a shebang or just tab complete hell<tab> which you should do with most commands anyway so the .py doesn't matter
another option would be to alias but you'd have to do that manually for every frequent script you need
Tab complete does not work if the script isn't at CWD, which is the case here since all my script is at ~/bin/.
Tab complete should still work if ~/bin is in $PATH.
Linux can do this. There are probably more ways, but this is off the top of my head.
Use an alias which you set up in your initialization scripts. You alias "hello" to "python3 /yada/yada/hello.py" which is essentially what Windows is doing for you behind the scenes.
You could even write a script to traverse all the files in your bin directory and make all the aliases.
Others have already mentioned how to fix your problem, but I just want to mention one thing about why:
On Linux (really, all platforms other than Windows), file extensions are much less of a thing; executables of any kind have no extension just the +x flag (among other things, this means you can rewrite them in another language without breaking anything).
The .py extension is only relevant for modules meant to be imported; for scripts being run, if you really need to know, you are supposed to look at the shebang (usually #!/usr/bin/env python for externally-distributed scripts; this gets overwritten to #!/usr/bin/python or whatever for scripts packaged by the distro itself).
Note also that, while shebangs don't support multiple arguments, the GNU version of `env` supports a `-S` argument that can emulate them (the argument length problem remains though).
File name extensions.[1]
I'm not saying you're wrong, but let's be clear about what these are. I would point out that Linux inherited some, but not all of its naming conventions from Unix (as did macOS), but at least here, that is a secondary concern.
Carry on...
[1]: https://arstechnica.com/gadgets/2001/08/metadata/
There is, but not in the shell syntax. It's an application concern normally delegated to the desktop/GUI.
For shell scripts, the executable is usually declared in the script itself, by adding a Shebang and making the file executable. Think of the Shebang like a file extension of sorts.
If
does not work, check the path the Shebang points to.That being said, as long as an interpreter can execute the scripts as regular argument, you should be able to get this behavior also for xdg-open:
if you really want to do that by default.This should be equivalent to double-clicking file in the default file manager, IIRC (am on Mac now).
I had an alias "xop <file>" when using Linux as my primary desktop OS.
But I only used this for data files (images, documents etc) where the default already works.
Wouldn't recommend setting an interpreter as default for executable scripts.
You might want to not execute scripts by default, instead opening them in an editor for example.
xdg-open is a Gnome thing I think, but that doesn't mean it's unavailable for other desktops. I know it from Xubuntu (so Xfce).
So I'd really advise against that, But if you want to execute all python files by default in any GUI context, too you could set this kind of default there
'man xdg-open' might help, or maybe you could even select a specific Python executable as the default for .py files after double-clicking in the File Manager.
Again, bad advice
On Ubuntu and probably Debian, the 'mailcap' package is (I think) installed by default. It provides the 'see', 'view', 'edit', 'print' and 'compose' commands which open a file in a suitable default program.
You could have a shim script with the shebang that only exists to call the "real" script using Python.
/usr/bin/hello:
/usr/bin/hello.py: Console:Why is this response being marked down? Just off the top of my head Sublime and VSCODE do this. I prefer `/usr/local/bin` since your package manager won't touch it.
Sublime:
VSCODE:Simply remove the .py from the filename. It's perfectly acceptable to call it "hello".
I can't think of a downside to the shebang. If you really wanted to run the script with a different interpreter, just specify it. "nohtyp hello" or whatever.
If that still bothers you too much, you could define an alias in your shell startup. For example, in bash, you might do:
alias hello="python3 /path/to/hello.py"
If you were so inspired, you could even write a short script to automatically create such aliases for the contents of a directory you specify.
Node seems to be partial to whether one has a .mjs or not on the filename.
The normal way here is to name your script simply `hello`, start it with a shebang reading `#!/usr/bin/env python3`, and mark it executable. This of course makes running it as `hello` work (if you put it in PATH), but also:
- The shebang is only specially interpreted by the Linux loader, i.e. when executing the file directly.
- You can still run it with any other interpreter in the standard way: `nohtyp ~/bin/hello`. Python comments start with `#`, so the shebang does nothing with programs expecting Python code.
- This situation (a script without an extension) is common on Linux, so Linux-aware editors understand the shebang to indicate a file type. At least, vim understands this and automatically detects a python file type without the .py extension.
I get your wish of Windows-like behaviour, and even if you might be able to conspire to have Linux behave the way you want, it's certainly not how people expect it to work, so prefer the above scheme for any software you send to others. :)
I used to think this as well, but I've since come around to the opposite view. Having it as a "requirement" for what's likely the most popular cli execution strategy enforces a (somewhat disorganised but still useful) defacto standard across all scripts. I can open up any repo/gist/pastebin in the world & chances are if it's intended to be run, it'll contain this handy little statement of intent on the first line. I might not actually run (env-dependent) but I'm sure I can make it.
On the env-sensitivity though, if e.g. you're running nohtyp, as another commenter mentioned, /usr/bin/env has that covered.
I believe the elegant solution to this is update-alternatives, which lets you tell the system which actual program to call. Maybe look into update-alternatives, I haven't looked into this much but it seems like it might interest you particularly. That's the closest equivalent to file association for the UNIX shell I would guess.
You could also have a specific folder that you control in your PATH that symlinks to the Python you want to use.
This handles the default, but you can still call your script with the program you want if you ever wish to bypass that.
You can utilize `command_not_found_handle()` for the extension-less behavior.
You can use the /usr/bin/env python shebang line to work across python location
I keep all my scripts in ~/git/$Project and symlink them into ~/bin and I've added ~/bin to the end of my path.
can't you use a shebang in Linux with .py files? And, as for removing .py, just remove the extension and make it executable or use a symlink
from a google search, https://stackoverflow.com/a/19305076
I'm not at the computer now to test though
You can run /usr/bin/nohtyp hello.py even on a script with a shebang specifying a different executable.
To remove the .py just rename the file to “hello”, or keep “hello.py” and create a symlink or a shell alias called “hello” that points to it.
Linux has a feature called 'binfmt_misc' which allows you to associate an interpreter to run when a file of any arbitrary format is invoked like an executable. You have to tell the kernel which extension or format is associated with which interpreter, but this is easily done in a startup script.
You still have to say '.py' at the end, though.
You don't need the file to be named "hello.py". You can name it just "hello", with the right shebang it will work fine.