文件夹的遍历

电脑上的文件夹遍历函数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