def dir_L2(Dir,keyword):
for x in os.listdir(Dir):
if os.path.isdir(x):
nextDir=os.path.join(Dir,x)
dir_L2(nextDir,keyword)
else:
if keyword in x:
print(os.path.join(Dir,x).replace(os.getcwd(),'.'))
....
#当遍历到当前目录下第三层的文件夹FILE2(ROOT-FILE1-FILE2)时,os.path.isdir会返回False
#导致不遍历子文件中的所有文件
经过测试后修改如下
def dir_L2(Dir,keyword):
for x in os.listdir(Dir):
nextDir=os.path.join(Dir,x)
if os.path.isdir(nextDir):
dir_L2(nextDir,keyword)
else:
if keyword in x:
print(nextDir.replace(os.getcwd(),'.'))
....
#此时可成功判断
我们来首先看看os.path.isdir源代码如下(VS2019看源代码:Ctrl+左键)
def isdir(s):
"""Return true if the pathname refers to an existing directory."""
try:
st = os.stat(s)
except OSError:
return False
return stat.S_ISDIR(st.st_mode)
def S_ISDIR(mode):
"""Return True if mode is from a directory."""
return S_IFMT(mode) == S_IFDIR
S_IFDIR = 0o040000 # directory
def S_IFMT(mode):
"""Return the portion of the file's mode that describes the
file type.
"""
return mode & 0o170000
struct stat {
dev_t st_dev; /* device */
ino_t st_ino; /* inode */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device type (if inode device) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for filesystem I/O */
blkcnt_t st_blocks; /* number of blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};
其中,st_mode
的类型mode_t
.
mode_t
其实就是普通的```unsigned int.``
目前,st_mode使用了其低19bit. 0170000 => 1+ 3*5 = 16.
其中,最低的9位(0-8)是权限,9-11是id,12-15是类型。
具体定义如下:
S_IFMT 0170000 bitmask for the file type bitfields
S_IFSOCK 0140000 socket
S_IFLNK 0120000 symbolic link
S_IFREG 0100000 regular file
S_IFBLK 0060000 block device
S_IFDIR 0040000 directory
S_IFCHR 0020000 character device
S_IFIFO 0010000 fifo
S_ISUID 0004000 set UID bit
S_ISGID 0002000 set GID bit (see below)
S_ISVTX 0001000 sticky bit (see below)
S_IRWXU 00700 mask for file owner permissions
S_IRUSR 00400 owner has read permission
S_IWUSR 00200 owner has write permission
S_IXUSR 00100 owner has execute permission
S_IRWXG 00070 mask for group permissions
S_IRGRP 00040 group has read permission
S_IWGRP 00020 group has write permission
S_IXGRP 00010 group has execute permission
S_IRWXO 00007 mask for permissions for others (not in group)
S_IROTH 00004 others have read permission
S_IWOTH 00002 others have write permisson
S_IXOTH 00001 others have execute permission
def S_IFMT(mode):
"""Return the portion of the file's mode that describes the
file type.
"""
return mode & 0o170000
def S_ISDIR(mode):
"""Return True if mode is from a directory."""
return S_IFMT(mode) == S_IFDIR
S_IFDIR = 0o040000 # directory
S_IFMT()
将传入的mode_t
类型参数与S_IFMT=0o170000
位与,由上述知,S_IFMT
为文件类型位域的位掩码,所得结果为文件的特征(包括权限、ID、类型)——此处我们需要文件类型——S_IFDIR ==0o040000
def isdir(s):
"""Return true if the pathname refers to an existing directory."""
try:
st = os.stat(s)
except OSError:
return False
return stat.S_ISDIR(st.st_mode)
此处便好理解了,若st.st_mode&S_IFMT==S_IFDIR
,则返回True
已知当前目录为I:\vs2019_Data\PythonLearning
PythonLearning下有目录I:\vs2019_Data\PythonLearning\.vs\PythonLearning\v16\.suo
import os
def dir(Dir):
for x in os.listdir(Dir):
dirinfo=os.stat(x)
nextDir=os.path.join(Dir,x) #下一文件路径
print('当前文件%s绝对路径为:%s'%(x,nextDir))
dirtype=dirinfo.st_mode & 0o170000
print('文件类型代码:%o'%dirtype)
dir(nextDir)
Dirpath='I:\\vs2019_Data\\PythonLearning'
dir(os.getcwd())
#运行结果如下
已加载“__main__”
已加载“runpy”
当前文件.vs绝对路径为:I:\vs2019_Data\PythonLearning\.vs
文件类型代码:40000
[WinError 2] The system cannot find the file specified: 'PythonLearning'
堆栈跟踪:
> File "I:\vs2019_Data\PythonLearning\code_test.py", line 4, in dir
> dirinfo=os.stat(x)
> File "I:\vs2019_Data\PythonLearning\code_test.py", line 9, in dir
> dir(nextDir)
> File "I:\vs2019_Data\PythonLearning\code_test.py", line 12, in <module>
> dir(os.getcwd())
根据输出:[WinError 2] The system cannot find the file specified: ‘PythonLearning’
问题出在dirinfo=os.stat(x)
,此处无法判断文件夹PythonLearning的stat特征。
import os
def dir(Dir):
for x in os.listdir(Dir):
dirinfo=os.stat(x)
print('当前目录:%s'%os.getcwd())
nextDir=os.path.join(Dir,x) #下一文件路径
print('当前文件%s绝对路径为:%s'%(x,nextDir))
dirtype=dirinfo.st_mode & 0o170000
print('文件类型代码:%o'%dirtype)
os.chdir(nextDir)
dir(nextDir)
Dirpath='I:\\vs2019_Data\\PythonLearning'
dir(os.getcwd())
由于是判断x
的特征,且每次遍历到第三层文件夹时,便报错。故我判断可能是当前工作目录(os.getcwd()
可获得当前工作目录)一直未更新,故造成第三层文件夹名称x
与当前目录之间出现断裂,解释器无法判断当前x
的stat
故上述代码在每次循环修改了当前目录,测试成功,输出如下
显然,经过修改当前目录,其文件代码类型显示正确。
os.path.isdir判断文件夹却返回 false的原因是:
当前目录与所遍历文件夹之间路径出现断裂,导致在判断时无法返回正确的st_mode
。