2

I'm on Windows 10 and decided to transition from cmd to Git Bash. Say I have a script foo.sh, I'd like to be able to run it with the command foo and not foo.sh. I found this answer, which works in some cases but not all:

  1. It only works if the script is in PATH. If it's just a script in my current directory, all the following forms don't work: foo, ./foo, foo.sh. The only way that works is ./foo.sh (so I still have to type the extension). I would expect ./foo to work, I don't know why it doesn't. It's as if the command not found handler doesn't even run in this case.

  2. I discovered that cd in a bash script doesn't work, you have to source the script like so: . foo.sh. Again, I'd like to be able to run . foo.

  3. It doesn't work in bash scripts that call other bash scripts.

So my question is how do I get rid of the need to type .sh everywhere, not just under specific circumstances.

EDIT: since I was asked, the output for assoc .sh on my machine is:

.sh=sh_auto_file

And the output for ftype sh_auto_file is:

sh_auto_file="C:\Program Files\Git\git-bash.exe" --no-cd "%L" %*

Verpous
  • 131
  • 3
  • Just [name the script `foo`](http://www.talisman.org/~erlkonig/documents/commandname-extensions-considered-harmful/). – Kamil Maciorowski Jul 11 '22 at 18:18
  • @KamilMaciorowski He wants to mimic Windows executable behavior from a Bash shell prompt. – Zhro Jul 12 '22 at 04:04
  • I understand what you are trying to do, and you may be able to find a workaround. But this isn't how it's done in Linux. Executables are determined by a bit flag in the filesystem and the program association is done either by a file header, in the case of a binary file, or a shebang for a text file. If you want to familiarize yourself with a Unix shell and filesystem characteristics, I would recommend that your learn how this is traditionally done. – Zhro Jul 12 '22 at 04:07

4 Answers4

2

This requires a couple steps.

  • Add .sh to the PATHEXT environment variable
  • Define an FTYPE for .sh ftype bash.File=c:\somepath\bash.exe "%1" %*
  • Define an assoc for .sh assoc .sh=bash.File

Similar to: https://stackoverflow.com/questions/9037346/making-python-scripts-run-on-windows-without-specifying-py-extension

uSlackr
  • 8,955
  • 31
  • 48
0

Bash requires an explicit filename, that's why you needed to perform such an obtuse workaround. It's also case sensitive, unless special consideration is being taken for a Windows environment.

What you're trying to do is shoehorn a Windows shorthand onto a Unix shell where it never existed. Outside of your trusted use case, it is also a security risk, for example, foo.exe could be dropped into the PATH and take priority.

My workaround for this was to adopt a habit of naming all executable shell scripts without the extension and all non-executable scripts (such as those that are includes or dependencies) with an extension. This has the added benefit of being easier to tab complete when there are files of similar, completable names, as it is already explicit without the extension.

Zhro
  • 837
  • 2
  • 15
  • 31
  • Getting rid of the file extension has some unwanted side effects. Text editors may fail to recognize the file type, and more importantly I will no longer be able to run scripts by double clicking them like an exe. – Verpous Jul 11 '22 at 18:40
  • You are correct. It's not a perfect workaround, but it's how I've decided to do it. The extension is also somewhat arbitrary anyways, since you have to make assumptions as to *which* shell is to be used. The correct way to handle this is with a shebang, at which point the extension becomes meaningless. Some editors for Windows may be able to read the shebang to determine which syntax highlighter to use, but there is no facility to bootstrap execution in this way natively without a file extension. – Zhro Jul 12 '22 at 04:00
  • Symlinking to the extensioned file is the more common approach. Bash doesn't require an explicit filename. It's windows – CervEd Nov 24 '22 at 09:16
  • nvm, it's the other way around. Still, symlinks are a nice alternative to moving files – CervEd Nov 24 '22 at 10:27
0

As @uSlacr points out, there are three steps.

You may run this .BAT file in an administrative command prompt to do them

:: Make .sh and .bash files executable without extension

:: Append .sh to PATHEXT
setx PATHEXT "%PATHEXT%;.SH;.BASH" /M
:: Define an FTYPE
FTYPE bash.File="C:/Program Files/Git/bin/bash.exe" "%%1" %%*
:: Define ASSOC for that FTYPE
ASSOC .sh=bash.File
ASSOC .bash=bash.File

The path to bash varies by how you installed git-for-windos. You can generate the .bat file in bash using

#!/bin/bash

bash_location="$(git --exec-path |
  sed 's@\(.*Git/\).*@\1bin/bash.exe@')"

printf '%s' ':: Make .sh and .bash files executable without extension

:: Append .sh to PATHEXT
setx PATHEXT "%PATHEXT%;.SH;.BASH" /M
:: Define an FTYPE
FTYPE bash.File="'"$bash_location"'" "%%1" %%*
:: Define ASSOC for that FTYPE
ASSOC .sh=bash.File
ASSOC .bash=bash.File
' > exec-sh-ext.bat

CervEd
  • 157
  • 8
0

Actually, it's just a matter of

  1. making sure your script is a Bash script, for which its first line should be #!/bin/bash
  2. removing the extension altogether, for example mv ./script1.sh ./script1
  3. making the file executable, for example chmod 777 ./script1
  4. (optionally) including the dir of your script in the PATH, for example export PATH="$HOME/my-scripts:$PATH"

If you do all 4 steps, then you can run your script with script1 from wherever.

Ando
  • 121
  • 3