#! /usr/bin/env python3 #指明python解释其的位置
# Variant of "which".
# On stderr, near and total misses are reported.
# '-l' argument adds ls -lof each file found.
import sys
if sys.path[0] in (".", ""): del sys.path[0] #1、了解列表sys.apth的作用; 2、了解"."与""的作用
import sys, os #make sure module os is imported from python
from stat import *
#定义出错函数
def msg(str):
sys.stderr.write(str + '\n') #写到了标准错误中
def main():
pathlist = os.environ['PATH'].split(os.pathsep) #注意sys.path与os.environ['PATH']的区别
sts = 0
longlist = '' #如果有 -l 则保存该字符串
if sys.argv[1:] and sys.argv[1][:2] == '-l': #argv[0]永远保存的是python脚本的名称。
longlist = sys.argv[1]
del sys.argv[1]
for prog in sys.argv[1:]:
ident = () #1、python原则,变量必须先定义后使用;2、注意,空的元组的作用
for dir in pathlist:
filename = os.path.join(dir, prog) #os.path.join is used to construct a path, not like join in class str
try:
st = os.stat(filename) #get the attribute of file
except os.error:
continue
if not S_ISREG(st[ST_MODE]): #it must be a disk file.
msg(filename + ': not a disk file')
else:
mode = S_IMODE(st[ST_MODE]) #获取文件的权限信息
if mode & 0o111: #确保是可执行文件
if not ident:
print(filename) #print the path information
ident = st[:3] #get the id infomation of i-node.
else:
if st[:3] == ident: #可能跟软/硬链接有关系,无论是软链接还是硬链接,id信息一致. 注意,判别多个值相等的方法.
s = 'same as: '
else:
s = 'also: '
msg(s + filename)
else:
msg(filename + ': not executable')
if longlist:
sts = os.system('ls ' + longlist + ' ' + filename) #os.system会打印信息,且成功后会返回0
if sts: msg('"ls -l" exit status: ' + repr(sts))
if not ident:
msg(prog + ': not found')
sts = 1
sys.exit(sts)
if __name__ == '__main__': #防止该py作为模块运行.
main()
总结如下:
1、S_ISREG(st[ST_MODE])的具体操作? 可将st理解为序列,所以ST_MODE就是一个数值下标,S_ISREG()是测试文件是否为普通文件,即ll时显示的'-'. 测试如下:
>>> from stat import *
>>> st = os.stat('ipt.sh')
>>> st
posix.stat_result(st_mode=33261, st_ino=3940080L, st_dev=2049L, st_nlink=1, st_uid=0, st_gid=0, st_size=170L, st_atime=1389791438, st_mtime=138979 1424, st_ctime=1389791433)
>>> ST_MODE
0
有对S_ISREG(st[ST_MODE])的使用进行测试, 地址为: S_ISREG测试文件是否是linux中的'-',普通文件.
2、which.py对软链接和硬链接的处理方式.
help(st)
st_ino inode
st_mode protection bits
st_dev device
注意:which.py并没有区分硬链接和软链接的不同,凡是这三部分相同就认为式统一个文件.
唯一表示节点的三部分信息. 尤其是i-node,在硬链接中,i-node的值是相同的,在软链接中值是不相同的。但是,测试结果却存在差异。
以下是在Linux下的测试结果.
Linux系统下:
3940080 -rwxr-xr-x 2 root root 170 1月 15 21:10 test2.sh
3937107 lrwxrwxrwx 1 xxxx xxxx 6 2月 20 21:31 test.sh -> ipt.sh
3940080 -rwxr-xr-x 2 root root 170 1月 15 21:10 ipt.sh
其中,test2是ipt.sh的一个硬链接,test.sh是ipt.sh的一个软链接。
Python测试如下:
>>> st = os.stat('test.sh')
>>> st
posix.stat_result(st_mode=33261, st_ino=3940080L, st_dev=2049L, st_nlink=2, st_uid=0, st_gid=0, st_size=170L, st_atime=1392902923, st_mtime=1389791424, st_ctime=1392903066)
>>> st = os.stat('test2.sh')
>>> st
posix.stat_result(st_mode=33261, st_ino=3940080L, st_dev=2049L, st_nlink=2, st_uid=0, st_gid=0, st_size=170L, st_atime=1392902923, st_mtime=1389791424, st_ctime=1392903066)
>>> st = os.stat('ipt.sh')
>>> st
posix.stat_result(st_mode=33261, st_ino=3940080L, st_dev=2049L, st_nlink=2, st_uid=0, st_gid=0, st_size=170L, st_atime=1392902923, st_mtime=1389791424, st_ctime=1392903066)
从以上打印结果可以看出,test.sh的inode值是不正确的。
在Python下,它认为硬链接和软链接是一样的,即它直接读软链接对应的文件的i-node信息.