补全了上一篇《Python 使用os库函数listdir() 模拟DOS命令dir》,基本上能够模仿 dir 和 dir/w 的显示结果:
驱动器 D 中的卷是 文档
卷的序列号是 109A-0446
D:\test 的目录
[.] [..] [01] 01.py [02]
02.py [03]
2 个文件 2,748 字节
5 个目录 315,430,735,872 可用字节
驱动器 D 中的卷是 文档
卷的序列号是 109A-0446
D:\test 的目录
2021/05/02 23:48 <DIR> .
2021/05/02 23:48 <DIR> ..
2021/05/02 22:56 <DIR> 01
2021/04/03 12:09 1,486 01.py
2021/05/02 22:56 <DIR> 02
2021/04/03 12:09 1,262 02.py
2021/05/02 23:48 <DIR> 03
2 个文件 2,748 字节
5 个目录 315,430,735,872 可用字节
驱动器 E 中的卷是 数据
卷的序列号是 109A-0537
E:\ 的目录
2021/05/04 23:39 <DIR> 【Download】
2021/05/04 21:19 <DIR> 【ScannedDoc】
2021/05/04 21:18 2,410,344 杨程驾驶证证件照.png
1 个文件 2,410,344 字节
2 个目录 300,126,973,952 可用字节
代码:
import os,time from win32api import GetVolumeInformation as DiskVolume from win32api import GetDiskFreeSpaceEx as FreeSpace def attrib(fn): from win32api import GetFileAttributes as attr ret=str(bin(attr(fn))) del attr if ret[-2]=='0': return True else: return False def pyDir(path=None,para=None): if path==None: path=os.getcwd() dt=lambda x:time.strftime('%Y/%m/%d %H:%M ',time.localtime(x)) cnCount=lambda str:len([i for i in str if '\u4e00'<=i<='\u9fff']) _time=dt(os.path.getmtime(path)) print(u' 驱动器 '+path[0].upper()+ u' 中的卷是 '+DiskVolume(path[0:2])[0]) tmp=str(hex(DiskVolume(path[0:2])[1])).upper() if tmp[:2]=='0X': tmp=tmp[2:] diskVol=tmp[:4]+'-'+tmp[4:] print(u' 卷的序列号是',diskVol) print('\n '+path+u' 的目录\n') if path[-2:]!=':\\'and para!='/w': print(_time,'<DIR>'.ljust(14),'.') print(_time,'<DIR>'.ljust(14),'..') if path[-1]!='\\': path+='\\' if para==None: files=[i for i in os.listdir(path) if attrib(path+i)] _time=[dt(os.path.getmtime(path+i)) for i in files] _size=[os.path.getsize(path+i) for i in files] for i,fname in enumerate(files): print(_time[i],'<DIR>'.ljust(14) if os.path.isdir(path+fname) else format(_size[i],',').rjust(14),fname) elif para=='/w': files=[i for i in os.listdir(path) if attrib(path+i)] lenths=max([len(i)+cnCount(i)+2 if os.listdir(path) else len(i)+cnCount(i) for i in os.listdir(path)]) if lenths<=16: fw=16 elif 16<lenths<=20: fw=20 elif 20<lenths<=40: fw=40 elif lenths>40: fw=80 if path[-2:]!=':\\': print('[.]'.ljust(fw),end='') print('[..]'.ljust(fw),end='') for i,fname in enumerate(files): if (i+2)*fw%80==0: print() cnCount=lambda str:len([i for i in str if '\u4e00'<=i<='\u9fff']) print((fname.ljust(fw-cnCount(fname)) if os.path.isfile(path+fname) else '['+fname+']').ljust(fw-cnCount(fname)),end='') print() fileSize=format(sum([os.path.getsize(path+i) for i in files if os.path.isfile(path+i)]),',') fileCount=len([i for i in files if os.path.isfile(path+i)]) dirCount=len([i for i in files if os.path.isdir(path+i)]) if path[-2:]!=':\\':dirCount+=2 diskSize=format(FreeSpace(path[:2])[0],',') print(f'{fileCount} 个文件'.rjust(20),f' {fileSize} 字节'.rjust(20)) print(f'{dirCount} 个目录'.rjust(20),f'{diskSize} 可用字节'.rjust(20)) print() pyDir('D:\\test','/w') pyDir('D:\\test') pyDir('E:\\')
dir命令默认是不列出隐藏文件或目录的;如果要列出隐藏的,可以在上述代码找到两处 if attrib(path+i) 删除这个条件掉即可 ,此时相当于命令:dir/a
代码用GetVolumeInformation 、 GetDiskFreeSpaceEx 和 GetFileAttributes求硬盘分区的卷号序列号、剩余空间字节数、文件属性等。
GetVolumeInformation() 返回磁盘卷标信息,返回值是一个5元素的tuple,分别对应:
TCHAR lpVolumeNameBuffer[1024]; //硬盘卷标名称 DWORD dwVolumeSerialNumber; //序列号 DWORD dwMaximumComponentLength; //文件名最大长度 DWORD FileSystemFlags; //文件系统标志 TCHAR lpFileSystemNameBuffer[1024]; //文件系统名称
其实序列号转成16进制数后去掉0x标记再在中间插入-字符,就与DOS命令dir显示的一样:如“卷的序列号是 109A-0446”
GetDiskFreeSpaceEx() 返回磁盘可用空间,返回值是一个3元素的tuple,分别对应:
LARGE_INTEGER lpFreeBytesAvailableToCaller //调用者可用空间的字节数 LARGE_INTEGER lpTotalNumberOfBytes //磁盘总容量的字节数 LARGE_INTEGER lpTotalNumberOfFreeBytes //磁盘的可用空间的字节数
GetFileAttributes() 对应DOS命令attrib,可以查看和修改文件或目录的属性。返回值是以下列表中的单个数值或它们任意几个的和都可以。进制转换可得到一个最长为16位的二进制数,各位上0,1就表示是否有对应属性,如返回22即2+4+16表示系统隐藏目录。判断文件或目录是否隐藏,请参见上述代码中自定义函数 attrib(fn)
1 FILE_ATTRIBUTE_READONLY 只读
2 FILE_ATTRIBUTE_HIDDEN 隐藏
4 FILE_ATTRIBUTE_SYSTEM 系统
16 FILE_ATTRIBUTE_DIRECTORY 目录
32 FILE_ATTRIBUTE_ARCHIVE 存档
64 FILE_ATTRIBUTE_DEVICE 保留
128 FILE_ATTRIBUTE_NORMAL 正常
256 FILE_ATTRIBUTE_TEMPORARY 临时
......之后的不常用,一直到2^15