Last active
November 29, 2022 22:11
-
-
Save 505e06b2/f1141603df8a1ec40974ce8b9609b4d9 to your computer and use it in GitHub Desktop.
Shebang proxy, specifically for Windows
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import os, sys | |
import subprocess, shutil, shlex | |
from pathlib import Path | |
def getShebangLine(executable_path): | |
with open(executable_path, "rb") as f: | |
magic = f.read(2) | |
if magic != b"#!": | |
return None | |
shebang = f.readline() | |
return shebang.decode("utf8").strip() | |
def getPathext(additions): | |
parsed_pathext = (os.environ.get("PATHEXT") or "").split(os.pathsep) | |
return_value = parsed_pathext + additions | |
os.environ["PATHEXT"] = f"{os.pathsep}".join(return_value) | |
return return_value | |
def findCorrectExtension(parsed_pathext, extensionless_filepath): | |
for possible_extension in parsed_pathext: | |
potential_fullpath = Path(extensionless_filepath).with_suffix(possible_extension) | |
if potential_fullpath.is_file(): | |
return potential_fullpath | |
return extensionless_filepath | |
if __name__ == "__main__": | |
import argparse | |
parser = argparse.ArgumentParser(description="Parse an execute a shebang line from a script") | |
parser.add_argument("script_file", type=Path) | |
parser.add_argument("arguments", type=str, nargs="*") | |
args = parser.parse_args() | |
env_pathext = getPathext([".PS1", ".SH"]) | |
executable_path = args.script_file | |
if str(executable_path) == executable_path.name: #relative paths passed to else | |
absolute_executable_path = Path(shutil.which(executable_path.name) or executable_path.name) | |
else: | |
absolute_executable_path = (executable_path if executable_path.suffix else findCorrectExtension(env_pathext, executable_path)).resolve() | |
if not absolute_executable_path.is_file(): | |
print(f"Can't find \"{executable_path}\"", file=sys.stderr) | |
sys.exit(1) | |
if not os.access(absolute_executable_path, os.X_OK): | |
print(f"\"{absolute_executable_path}\" is not executable", file=sys.stderr) | |
sys.exit(1) | |
shebang = getShebangLine(absolute_executable_path) | |
if shebang == None: | |
print(f"\"{absolute_executable_path}\" does not have a shebang line", file=sys.stderr) | |
sys.exit(1) | |
parsed_shebang = shlex.split(shebang) | |
if os.name == "nt" and parsed_shebang[0] == "/usr/bin/env": | |
parsed_shebang[0] = "env" | |
subprocess.run(parsed_shebang + [absolute_executable_path] + args.arguments) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment