文件夹的遍历
电脑上的文件夹遍历函数os.walk(path)函数,是一切文件夹操作的基础。有了这个函数,全部文件夹与文件的操作就有了基础。本文要谈的是网盘上的文件夹遍历。考虑使用bypy工具搭建自己的网盘自动传输系统,需要对云文件夹进行遍历,如果建立同样的函数,将能为所有相关文件夹的文件的操作建立坚实的基础。
这个问题并不简单。因为文件夹具有循环特征。企图遍历完一个子文件夹再进入下一个子文件夹是困难的,因为遍历完子文件的操作就是遍历完全部文件夹的操作,它们在结构上是一致的。这引起了我对复杂程序结构分析的兴趣。
首先,要考虑突破这种陷阱。我考虑的是从第一层开始,到第二层,到第三层,一层一层遍历完文件夹,而非遍历完所有某个子文件夹的内容。
第二,构建循环体,这个循环体是对一个列表的操作,这个列表的文件夹进行操作,产生一系列的子文件夹,重新构成列表,把得到的新列表,赋给上一次被操作的那个列表用到的名字,就实现了循环。
第三,我们的操作基础是基于bypy本身提供的list函数,它会提供当前文件夹的子文件夹和文件信息,类似于os的listdir函数。不过它只能显示在shell中,所以要调用subprocess的runcmd函数,让运行结果写入文本文件,再通过文本文件的读写传递信息解决这个问题。
第四,对循环体的分析表明,需要在一个一般性变量的位置,即位于n的层级,不能指定具体的层级,只能是变量n,往上回溯到初始文件夹,获得路径才能调用list函数产生子文件夹列表。这就要求我们改造针对单层文件夹的 list函数,使在当前的n层级的操作获得n-1级的文件夹的信息,从而能够回溯到起点。
第五,循环体在初始位置很难与一般情况共用同样的程序代码组,我们可以修改在第一次循环时的处理就是了。循环熔断的条件,可以观察到产生的子文件夹列表为空时就可以break了。
下面是草图分析。在用草图进行分析完之后,整个代码的编写出奇顺利。因此正确的程序编写是要进行草图分析的,慢慢推断研究它各部分应该具备的特征和规律,并分析实现这些功能需要的信息和信息的传递。程序本质上是一台复杂的精密的机器。程序延展了数学的运算范围,并以其自身的逻辑使我们获得明确的输入输出的规律。有些结果是偏离甚至是不可知的诡异的,它指向某种神秘的精神灵性的层面。这些正是它的魅力所在。



这是listwj.py子程序
import bypy
from bypy import ByPy
bp = ByPy()
# 1 读取传入的网盘文件夹名
TEa = []
with open(r'D:\pythonZD\xitong\wpwjj.txt','r',encoding = 'utf-8') as file:
while True:
line = file.readline()
TEa.append(line)
if line == '':
break
mg = TEa[0]
bp.list(remotepath = mg)
如下的wp_walk(path)函数完全实现了如同电脑上操作的os.walk(path)函数一样的功能。
# -*- coding: utf-8 -*-
import subprocess
import os
import MKwjcz
from bypy import ByPy
bp = ByPy()
import win32com.client
import pythoncom
import math
import shutil
import time
import re
def runCmd(cmd) :
res = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
sout ,serr = res.communicate() #该方法和子进程交互,返回一个包含 输出和错误的元组,如果对应参数没有设置的,则无法返回
return res.returncode, sout, serr, res.pid #可获得返回码、输出、错误、进程号;
def wpread(pat):
stming = str(pat)
#1 写入传入的文件夹名
with open('D:/pythonZD/xitong/wpwjj.txt','w',encoding = 'utf-8') as file:
file.write(stming)
file.close()
def yxlist(pah):
# 1 将路径写入指定文件
wpread(pah)
if os.path.exists(r'D:\pythonZD\xitong\SD.txt'):
os.remove(r'D:\pythonZD\xitong\SD.txt')
# 2 运行子程序获得该文件夹的内容信息,存入列表
res1 = runCmd("python D:/pythonZD/YunXing/listwj.py >> D:/pythonZD/xitong/SD.txt" )
TE = []
with open(r'D:\pythonZD\xitong\SD.txt','r',encoding = 'GBK') as file:
while True:
line = file.readline()
print(line)
TE.append(line)
if line == '':
break
# 3 读取所有列表内容,获得所有文件夹名和文件名并分别存为列表返回
Dmg = []
Fmg = []
for xx in TE:
lba = xx.split()
if len(lba)>0:
if lba[0] == 'D':
Dmg.append(lba[1])
elif lba[0] == 'F':
del lba[0]
del lba[-1]
fg = '@'.join(lba)
Fmg.append(fg)
else:
pass
return Dmg, Fmg
def yxlist_jian(pah):
ss = pah #此句并非啰嗦
# 1 将路径写入指定文件
wpread(pah)
if os.path.exists(r'D:\pythonZD\xitong\SD.txt'):
os.remove(r'D:\pythonZD\xitong\SD.txt')
# 2 运行子程序获得该文件夹的内容信息,存入列表
res1 = runCmd("python D:/pythonZD/YunXing/listwj.py >> D:/pythonZD/xitong/SD.txt" )
TE = []
with open(r'D:\pythonZD\xitong\SD.txt','r',encoding = 'GBK') as file:
while True:
line = file.readline()
print(line)
TE.append(line)
if line == '':
break
# 3 读取所有列表内容,获得所有文件夹名和文件名并分别存为列表返回
Dmg = []
Ltb = []
for xx in TE:
lba = xx.split()
if len(lba)>0:
if lba[0] == 'D':
#将上一级文件夹的名字信息一起存储
cun = ss+'-'+lba[1]
Dmg.append(lba[1])
Ltb.append(cun)
else:
pass
return Ltb, Dmg
def wp_walk(PAT):
st = PAT
LBcao = []
LBcao.append(st)
# 1 建立循环体
GGlb = []#用于存放全部父链
Dlb = []#用于存放所有'各级遍历到的子文件夹名'列表
Luj = []#用于存放全部路径
chang =len(yxlist_jian(st)[1])
n = 0
while True:
Slb = [] #用于存放本级父链
Tlb = [] #用于存放本级文件夹名
for xm in LBcao: #在本级列表中操作
# 第一次操作LBcao的元不存在父链
if n > 0 and chang >0:
#对操作列表元做list产生子文件夹才能进行下面操作
#定义pp为上一级直到最原始的父文件夹序列,如何找到pp呢?yxlist_jian函数返回的第一个值就带了父的信息并存入公共列表 GGlb
#从本级列表LBcao中的每个元素,我们要回溯上一级的父名。例如本级LBcao的一个元如为B1-C1,那么B1指示了本级C1的父名为B1
#在公共大列表集GGlb中,我们先找到以B1结尾的元,就得到例如为A1-B1,反复计算直到最原始级
cv = xm
lianx = [] #存放xm的父链
while True:
h = cv.split('-')
le = len(lianx)#以xm父链列表长变化判断循环熔断break
## print(le)
for xi in GGlb:
t = xi.split('-')
if t[1] == h[0]:
## print(xi)
lianx.append(xi)
cv = xi #重新定义以便循环
#以xm父链列表长变化判断循环熔断break # 2 定义pp为上一级直到最原始的父文件夹序列
if le == len(lianx):
break
## print('lianx',lianx)
biax = []
biax.append(xm)
biax.extend(lianx)
pp = ''
## print(biax)
for i in range(len(biax)):
fl = biax[i]
ax = fl.split('-')[0]
pp = ax+'/'+pp
print('pp',pp) # 至此就找到了pp
xn = xm.split('-')[1]
w = yxlist_jian(pp+xn)[0]
v = yxlist_jian(pp+xn)[1]#文件夹名
Luj.append(pp+xn)
## print('v:',v)
#把xm元素用yxlist_jian操作的生成结果放入列表Slb
for uu in w:
Slb.append(uu)
GGlb.append(uu)
LBcao = Slb#存放一次操作生成的同级子文件夹数据
## print('对一个级别子文件夹操作后生成的下一级子文件夹',LBcao)
for cc in v:
Tlb.append(cc)
else:
w = yxlist_jian(st)[0]
v = yxlist_jian(st)[1]#文件夹名
for uu in w:
Slb.append(uu)
GGlb.append(uu)
LBcao = Slb#存放一次操作生成的同级子文件夹数据
## print('对一个级别子文件夹操作后生成的下一级子文件夹',LBcao)
for cc in v:
Tlb.append(cc)
Dlb.append(Tlb)#存放各级遍历到的子文件夹名
print('第',n,'次循环')
print('===============================')
n = n+1
## print('序号:',n)
if len(LBcao) == 0 :
break
Mb = [st]
ML = []
ML.append(Mb)
ML.extend(Dlb)
jg = []
for lu in Luj:
DF = yxlist(lu)
yuan = (lu,DF[0],DF[1])
jg.append(yuan)
return jg,ML