whichコマンド

which コマンドの実装
id:t2y-1979:20080409#1207749772

whichはPATHを頭から調べて最初に見つけたものを返すので、

  • 順序を保持しないsetに入れるとまずい
  • ループをbreakしないと最後に見つけたものを出力してしまう

と思います。

>>> set(['a', 'b', 'c', 'd'])
set(['a', 'c', 'b', 'd'])

順序が変わってます。
重複を排除するには、リストにuniqのようなメソッドがあればいいけど、ないみたいです。
こんな書き方ができました。ただ、遅いかも。

>>> l = ['a', 'b', 'b', 'c', 'a']
>>> [ x for i, x in enumerate(l) if x not in l[:i] ]
['a', 'b', 'c']

でも、頭から調べてbreakする処理なら、重複を排除しておく必要はないわけですが。
自分なりに書いたのが以下。

which2.py

import os, sys
cmd_name = sys.argv[1]
path_list = [ path for path in os.environ["PATH"].split(":") ]
for path in path_list:
    full_path = os.path.join(path, cmd_name)
    if os.access(full_path, os.X_OK):
        print full_path
        break
else:
    print "No such command. %s" % cmd_name

実行。

$ echo $PATH
/usr/local/java/jdk1.6/bin:/usr/local/flex2/bin:/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/home/michisu/bin

$ where python
/usr/local/bin/python
/usr/bin/python
/home/michisu/bin/python

$ which python
/usr/local/bin/python

$ python which2.py python
/usr/local/bin/python

$ python which2.py nocmd
No such command. nocmd