14

I am wondering if there is a Unix equivalent for the Windows environment variable PATHEXT.

For those with no Windows background: Adding a file suffix to PATHEXT allows me to execute a script without typing that suffix in cmd.exe. For example, on my Windows computer, PATHEXT contains the suffix .pl and when I want to execute a Perl script in cmd.exe, I simply can type my-script and it gets executed. Yet, in order to execute the same script in bash, I need to write the full name: my-script.pl.

Since I work on both Windows and Unix currently, I almost always fall into the trap of forgetting to type the suffix when going to a Unix box again.

3
  • It would be interesting to know what Windows did if PATHEXT contained, for example, .sh and .pl and you tried to run 'foo' in a directory with foo.sh and foo.pl in it.
    – Jeff Schaller
    May 3, 2016 at 2:02
  • If .sh preceedes .pl, foo.sh will be run. stackoverflow.com/a/7839178/180275 May 3, 2016 at 5:55
  • I have the same experience in WSL: it's unusual that I remember to type git.exe instead of git, and if git were the only one then an alias would be a fine solution, but I think I'll try the .bashrc solution below.
    – woodvi
    May 23 at 20:41

3 Answers 3

13

The simplest solution is to just not use extensions for your scripts. They are not necessary and only serve to identify the script's type to you, but not to the computer. While Windows uses extensions to identify the file type, *nix systems (with very few exceptions such as gzip) do not.

Note that binaries have no .exe extension in *nix, they're just called foo, not foo.exe. So, if you want foo.pl to be executable as foo, simply save the file as foo in the first place.

Alternatively, if you really need to have the extensions for some reason, go into whatever directory you save your scripts in and run this:

for f in *.*; do ln -s "$f" "${f%%.*}"; done

That will iterate over all files with extensions and, for each file foo.ext of them, will create a link called foo which points to foo.ext. Note that this will fail if you have multiple scripts with the same name but different extensions.

0
9

If you really want to do it, there is a way. Add the following at the end of .bashrc in your home directory, and set PATHEXT to extension names with dots separated by :. (Changed to include the dots to match the Windows behavior.) Use it at your own risk.

if declare -f command_not_found_handle >/dev/null; then 
    eval "original_command_not_found_handle() $(declare -f command_not_found_handle|tail -n +2)"
fi
command_not_found_handle(){
    local PATHEXT_EXPANDED i
    IFS=: read -a PATHEXT_EXPANDED<<<"$PATHEXT"
    for i in "${PATHEXT_EXPANDED[@]}"; do
        if type "$1$i" &>/dev/null; then
            "$1$i" "${@:2}"
            return $?
        fi
    done
    if declare -f original_command_not_found_handle >/dev/null; then
        original_command_not_found_handle "$@"
    else
        return 127
    fi
}

Also remember that you can use tab to complete the command name if there isn't another command also starting with my-script.

8

short: no

longer: shell scripts require a full filename, but you can define aliases for your commands to refer to them by various names. For example

alias my-script=my-script.pl

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .