An Introduction to the Command-Line (on Unix-like systems)

by Oliver; 2014

20. File Suffixes

As we begin to script it's worth following some file naming conventions. We should use common sense suffixes, like:
  • .txt - for text files
  • .html - for html files
  • .sh - for shell scripts
  • .pl - for Perl scripts
  • .py - for Python scripts
  • .cpp - for c++ code
and so on. Adhering to this organizational practice will enable us to quickly scan our files, and make searching for particular file types easier [1]. As we saw above, commands like ls and find are particularly well-suited to use this kind of information. For example, list all text files in the cwd:
$ ls *.txt
List all text files in the cwd and below (i.e., including child directories):
$ find . -name "*.txt"



[1] An astute reader noted that, for commands—as opposed to, say, html or text files—using suffixes is not the best practice because it violates the principle of encapsulation. The argument is that a user is neither supposed to know nor care about a program's internal implementation details, which the suffix advertises. You can imagine a program that starts out as a shell script called mycommand.sh, is upgraded to Python as mycommand.py, and then is rewritten in C for speed, becoming the binary mycommand. What if other programs depend on mycommand? Then each time mycommand's suffix changes they have to be rewritten—an annoyance. Although I make this sloppy mistake in this article, that doesn't excuse you! Read the full argument

Update: There's a subtlety inherent in this argument that I didn't appreciate the first time around. I'm going to jump ahead of the narrative here, so you may want to skip this for now and revist it later. Suppose you have two identical Python scripts. One is called hello.py and one is simply called hi. Both contain the following code:
#!/usr/bin/env python

def yo():
    print('hello')
In the Python shell, this works:
>>> import hello
but this doesn't:
>>> import hi
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named hi
Being able to import scripts in Python is important for all kinds of things, such as making modules, but you can only import something with a .py extension. So how do you get around this if you're not supposed to use file extensions? The sage answers this question as follows:
The best way to handle this revolves around the core question of whether the file should be a command or a library. Libraries have to have the extension, and commands should not, so making a tiny command wrapper that handles parsing options and then calls the API from the other, imported one is correct.
To elaborate, this considers a command to be something in your PATH, while a library—which could be a runnable script—is not. So, in this example, hello.py would stay the same, as a library not in your PATH:
#!/usr/bin/env python

def yo():
    print('hello')
hi, a command in your PATH, would look like this:
#!/usr/bin/env python

import hello

hello.yo()
Hat tip: Alex

<PREV   NEXT>