0

So I want to make a CLI using a python package for that but I also want to call the CLI with just a simple command like "myCli" from anywhere within my user account (or system wide flexible on that).

My current solution is the following but it seems very hacky:

in ~/scripts/

~/scripts me$ cat hiPython 
python ~/scripts/hi.py
~/scripts me$ cat hi.py
print("im python")

In bash_profile (on a mac):

export PATH="/Users/me/scripts:$PATH"

This seems to work

~/Desktop me$ hiPython
im python

Is there a less brittle/dangerous way?

Bren
  • 3,516
  • 11
  • 41
  • 73
  • 1
    Can you explain what you find dangerous/brittle/hacky about this solution? – Fred Apr 12 '17 at 01:46
  • 1
    @Fred it requires a file just to call another file and adds an entire directory to the path. – Bren Apr 12 '17 at 01:50
  • 1
    That's literally the entire purpose of the path. – Mad Physicist Apr 12 '17 at 01:57
  • @MadPhysicist is right, this "hack" is the basic mechanism by which commands specified without a path are matched with actual executable files on any UNIX-like system (that I have been in contact with). – Fred Apr 12 '17 at 02:01
  • @MadPhysicist yeah but it still requires editing the bash_profile and adding a file to the path. The accepted answer (with the addition of my comment) shows a standardized and far less obtrusive way of doing the same thing (hence why most CLIs take that approach). – Bren Apr 12 '17 at 02:04

3 Answers3

3

You need to do three things.

  1. Add #!/usr/bin/python (or whatever appropriate path to your interpreter) as the first line in your script
  2. chmod +x your script to mark it as executable
  3. Make sure the script is in a directory that is found in the PATH environment variable

I would recommend making sure its name is unique to avoid any collision with anything else on the system.

Fred
  • 6,590
  • 9
  • 20
  • yep. thanks for further info it looks like /usr/local/bin is the place to put these things (and the .py can be left off). – Bren Apr 12 '17 at 02:02
  • @Bren the `.py` extension has no influence on how the file is executed. It can be used as an indicator of file content, but the OS does not rely on it. – Fred Apr 12 '17 at 02:05
  • exactly why I mentioned it could be left off. – Bren Apr 12 '17 at 02:06
1

I don't perfectly understand your question but perhaps alias would work?

> alias myCli="python ~/LocationOfPythonFile/hiPython.py
> myCli
> im python

see http://tldp.org/LDP/abs/html/aliases.html

axwr
  • 2,118
  • 1
  • 16
  • 29
  • you got the question thats a pretty good answer. I am curious though for things like brew and even python itself how is this done? They aren't in the .bash_profile – Bren Apr 12 '17 at 01:49
  • 1
    @Bren Well, I hate to have to tell you this, but basically all commands that can be specified with a single word (that are not shell builtins) are found thanks to the `PATH` variable... – Fred Apr 12 '17 at 01:51
  • @Fred not sure why you hated having to tell me that, it was useful. – Bren Apr 12 '17 at 02:05
  • @Bren Because your question seemed to imply you did not like using the `PATH` variable... – Fred Apr 12 '17 at 02:06
1

The typical approach is to use #! notation (google it as "shebang").

Create one file called hiPython. Use chmod to give yourself permission to execute it, and make sure it's located in a directory that's listed in $PATH (you seem to know how to do both of those steps already). In the file, make sure the very first line starts with #! and then specifies which interpreter should be used for the rest of the file:

#!/usr/bin/python
print("I'm Python")

People very often use env in this context, for flexibility:

#!/usr/bin/env python
print("I'm Python")

since that finds the first python binary on your current $PATH rather than a hardcoded version/distro of python.

NB: this isn't unique to Python. You can use this method to associate any file with any executable you like. There are some creative off-label uses of this, but usually it's for associating a script with its interpreter.

jez
  • 14,867
  • 5
  • 37
  • 64
  • 1
    In order to be able to execute a script without specifying its path, you have to both use the shebang described here, AND have this script be executable, AND have it in a directory present in the `PATH` variable. – Fred Apr 12 '17 at 01:55
  • 1
    technically, the script does not have to interpret hashes as a comment. That line is read and stripped off by the shell before the remainder is passed to the interpreter. You can use shebang anywhere as long as it's the first two characters and you have execute permissions, even in a binary file. – Mad Physicist Apr 12 '17 at 02:00
  • @MadPhysicist that's cool, I didn't know that. – jez Apr 12 '17 at 02:06