A Simple Unix Shell in Python
Published: April 16, 2008Tags: python unix programming
Here is an absolute bare-minimum Unix shell written in just 36 lines of Python (including a few blank lines). It doesn't do pipelines, input/output redirection, tab-completion or have a command history, it's just a really light wrapper around the fork, execv and wait system calls, using the os module. The only internally implemented function is cd because a shell is a painful thing to use without it.
from os import chdir, execv, fork, getenv, wait
from os.path import exists
from sys import exit
while True:
# Get input
prompt = getenv("PS1", "$ ")
try:
input = raw_input(prompt)
except EOFError:
exit()
# Parse input
argv = input.split()
command = argv[0]
# Do inbuilts
if command == "cd":
if len(argv) == 1:
chdir(getenv("HOME", "/"))
else:
chdir(argv[1])
# Do external
else:
found = False
path = getenv("PATH")
for dir in path.split(":"):
if exists("/".join((dir, command))):
found = True
if(fork() == 0):
execv("/".join((dir, command)), argv)
else:
wait()
if not found:
print "%s: Not found" % command
This works quite smoothly, it doesn't feel laggy or anything when you're actually using it. I suppose this isn't unusual because the Python code in use probably just directly calls the underlying C system calls. It's really pretty neat, if not slightly silly.
I have a somewhat more complicated version working, but at the moment it's still looking a bit too ugly to post in a blog entry - it handles interpolation of environment variables, multiple semi-colon delimited commands on a line and has the beginnings of pipeline and redirection support.
I think I'll end up writing an article that explains how Unix shells work, using a Python shell as an example (because it's much easier for the average person to read than C), and put the complete shell up on my software page.
On an unrelated note, here's Super Mario World implemented in Javascript. Wow.