Recently I had blogged about which.py, a simple Python program that I wrote, here:
A simple UNIX-like 'which' command in Python
I also posted the same program on ActiveState Code:
A UNIX-like "which" command for Python (Python recipe)
A reader there, Hongxu Chen, pointed out that my which.py actually implemented the variant "which -a", that is, the UNIX which with the -a (or -all) option included. This variant displays not just the first full pathname of an occurrence of the searched-for name in the PATH (environment variable), but all such occurrences, in any directory in the PATH. That was not what I had intended. It was a bug. I had intended it to only show the first occurrence.
So I rewrote the program to fix that bug, and also implemented the -a option properly - i.e. when -a (or its long form, --all, is given, find all occurrences, otherwise only find the first. Here is the new version:
from __future__ import print_function # which.py # A minimal version of the UNIX which utility, in Python. # Also implements the -a or --all option. # Author: Vasudev Ram - www.dancingbison.com # Copyright 2015 Vasudev Ram - http://www.dancingbison.com import sys import os import os.path import stat def usage(): sys.stderr.write("Usage: python which.py [ -a | --all ] name ...\n") sys.stderr.write("or: which.py [ -a | --all ] name ...\n") def which(name, all): for path in os.getenv("PATH").split(os.path.pathsep): full_path = path + os.sep + name if os.path.exists(full_path): print(full_path) if not all: break def main(): if len(sys.argv) < 2: usage() sys.exit(1) if sys.argv[1] in ('-a', '--all'): # Print all matches in PATH. for name in sys.argv[2:]: which(name, True) else: # Stop after printing first match in PATH. for name in sys.argv[1:]: which(name, False) if "__main__" == __name__: main()I tested it some and it seems to be working okay both with and without the -a option now. After more testing, I'll upload it to my Bitbucket account. - Vasudev Ram - Online Python training and programming Dancing Bison EnterprisesSignup to hear about new software or info products that I create. Posts about Python Posts about xtopdf Contact Page
2 comments:
Your which.py does not check if the file it has found is really a file (as opposed to a dir) and has executable permissions.
So run this: mkdir /usr/bin/spamm; touch /usr/local/bin/spamm
Then "which.py spamm" should give nothing, but gives:
/usr/bin/spamm
/usr/local/bin/spamm
Thanks for your comment. You are right about those checks (for a dir or an exe file) not being done. But did you read the previous post that I linked to:
A simple UNIX-like "which" command in Python
in which (pun intended:) I said:
"I'll discuss my interpretation of these variations in an upcoming post - including a variation that uses os.stat(full_path).st_mode:"?
If you look at that commented code fragment, you'll see that it includes a check for if a file is executable, i.e.:
if os.stat(full_path).st_mode & stat.S_IXUSR:
And I have not yet written that "upcoming post". However, I had not thought of checking for the file being a directory as well (good point), which I will now do in that next post, including trying to take care of the case where a file can be a dir (with execute bit set), and excluding that case (at least on UNIX, need to see if Python supports checking for that on Windows).
Post a Comment