2

This may be confusing.

rootdir= C:\User\Desktop\File
file = 'file.txt'

mainLocNum = str(list(rootdir)).count(r'\\')
mainFolder=os.listdir(rootdir)

with open(file,'w') as f:

    for dir, subdirs, files in os.walk(rootdir):
        currentDirLevel=str(list(dir)).count(r'\\')
        for allFolders in subdirs:
            if (currentDirLevel - mainLocNum) == 0:
                parentFolders=allFolders
                f.write(str(parentFolders))
                PLACEHOLDER
            elif (currentDirLevel - mainLocNum) == 1:
                subFolders=allFolders
                f.write(str(allFolders)     <----- write this in PLACEHOLDER

I want to write the second write statement into the PLACEHOLDER line only if the elif condition is met. If I don't write the second write statement in the PLACEHOLDER position, the second write statement in the second conditional is written at the very bottom of the text file; however I want to write the second conditional's write statement (only if it is met) in the PLACEHOLDER position, which is in between each of the first write iterations.

I've been trying different nesting methods, but I am lacking in fundamental loop construction logic.

Any help is appreciated, thanks!

EDIT:

I am looping through a main directory, and I am writing all of the parent folders into the text file. I want to write in between each parent folder its subfolders: i.e if the parent folder contains more folders, to write those folders in between each parent folder; and if the parent folder does not contain any more folders, to skip to the next parent folder etc. I am using the if (currentDirLevel - mainLocNum)==(number) to know how many directories it is stepping into and to perform a different write function for each step.

I am trying to write the names of the folders in certain formats depending on whether they are level 1 sub-directories, level 2 sub-directories etc...

What I want:

ParentFolder1
    SubFolder1
    Subfolder2
        SubSubFolder1
    SubFolder3
ParentFolder2
    SubFolder1
ParentFolder3
ParentFolder4
    SubFolder1
        SubSubFolder1
            SubSubSubFolder1
        SubSubFolder2
    SubFolder2
ParentFolder5
    SubFolder1

What I am getting

ParentFolder1
ParentFolder2
ParentFolder3
ParentFolder4
ParentFolder5
SubFolder1
SubFolder2
SubFolder3
SubFolder1
SubFolder1
SubFolder2
SubFolder1
SubSubFolder1
SubSubFolder1
SubSubFolder2
SubSubSubFolder1

Please don't focus on the os.walk or iterating through the directories. I have a lot of code written already, and I want the main focus to answer my question about running a conditional loop and placing the value within that loop into a write function inside another loop.

I would prefer restructuring this loop logic rather than starting over with the whole os.walk for loop.

Thanks again

Mike Issa
  • 295
  • 2
  • 13
  • 1
    you cant iterate through a file if its opened with `'w'` – R Nar Nov 24 '15 at 17:51
  • Thanks, I will edit the question. I rushed into simplifying my situation. – Mike Issa Nov 24 '15 at 17:53
  • 1
    Are you trying to write a script that opens itself and rewrites its own code? Does "file" refer to this file? Or some other file? – Kevin Nov 24 '15 at 17:55
  • 1
    So you only want `f.write(i+command2)` to run if `x == certain_value`? – NotAnAmbiTurner Nov 24 '15 at 17:57
  • I put a lot more detail into what is going on. I hope this clarifies things a bit. – Mike Issa Nov 24 '15 at 17:59
  • 1
    Make sure you post something that "works" as in, shows your error if I were (hypothetically) to run it myself. That means I also need some data that you are using, and to know what the output is that you are expecting but not getting. – DisappointedByUnaccountableMod Nov 24 '15 at 18:00
  • 1
    Can you describe in words *exactly* what you want your program to do? – DisappointedByUnaccountableMod Nov 24 '15 at 18:02
  • OK, I will try my best. I am looping through a main directory, and I am writing all of the parent folders in the text file. I want to write in between each parent folder its subfolders, i.e if the parent folder contains more folders, to write those folders in between each parent folder; and if the parent folder does not contain any more folders, to skip to the next parent folder etc. I am using the if (currentDirLevel - mainLocNum)==(number) to know how many directories it is stepping into and to perform a different write function for each step. – Mike Issa Nov 24 '15 at 18:04
  • 1
    Add this description into the question. by "writing" you mean like "printing"? – DisappointedByUnaccountableMod Nov 24 '15 at 18:09
  • Thanks, I updated the question. Yes, I am trying to write the names of the folders in certain formats depending on whether they are level 1 sub-directories, level 2 sub-directories etc... – Mike Issa Nov 24 '15 at 18:11
  • 1
    A fairly fundamental problem you have with using os.walk() is that it doesn't go depth-first which is what you need. os.walk() goes width-first - it gives you all the folders at the current level before going into the subfolders. – DisappointedByUnaccountableMod Nov 24 '15 at 18:42
  • 1
    Never forget goggle is your friend. A quick search turns up this - the expected answer is what you want, I think. http://stackoverflow.com/questions/9727673/list-directory-tree-structure-using-python – DisappointedByUnaccountableMod Nov 24 '15 at 18:45
  • 1
  • Thanks, but I was hoping someone would explain how to work with the 'if' conditionals and running the command from the conditional block into another loop (the whole "PLACEHOLDER" thing). I didn't want an answer leading me on to re-write and re-think the os.walk loop logic. – Mike Issa Nov 24 '15 at 19:13

1 Answers1

3

I'm not quite sure what you mean by the term "conditional loop", but what you're trying to achieve is easily done using a small recursive function based on os.listdir. You could do this using os.walk, but I often find it simpler (and more efficient) to call os.listdir explicitly (os.walk calls os.listdir internally), especially when you don't need separate lists of directories and plain files.

import os

tab = 4 * ' '

def writedirs(fhandle, path, depth=0):
    ''' Recursively walk the directory tree starting at path,
        writing all directory names to open file handle fhandle.
        Nodes are traversed depth-first, top-down, and names
        are indented proportional to their depth.
    '''
    data = os.listdir(path)
    # Names returned by listdir are in file system order;
    # If you want them sorted alphabetically, call
    # data.sort()
    # or
    # data.sort(key=str.lower)
    # for case-insensitive sorting.

    indent = depth * tab
    depth += 1
    for filename in data:
        fullpath = os.path.join(path, filename)
        if os.path.isdir(fullpath):
            fhandle.write(indent + filename + '\n')
            writedirs(fhandle, fullpath, depth)

#Test
rootdir = 'testfolder'
outname = 'file.txt'
with open(outname, 'w') as fhandle:
    writedirs(fhandle, rootdir)

contents of 'file.txt'

ParentFolder1
    SubFolder1
    Subfolder2
        SubSubFolder1
    SubFolder3
ParentFolder2
    SubFolder1
ParentFolder3
ParentFolder4
    SubFolder1
        SubSubFolder1
            SubSubSubFolder1
        SubSubFolder2
    SubFolder2
ParentFolder5
    SubFolder1

It's generally better to avoid recursion in Python, when practical: the Python interpreter cannot perform tail call elimination, and it imposes a maximum recursion depth. However, when dealing with recursive data structures (like file trees) it's natural to use a recursive algorithm.


FWIW, the code below iteratively performs the inverse operation of the code above; I used it to build the directory tree from the indented list of directory names given in the question.

import os

data = '''
ParentFolder1
    SubFolder1
    Subfolder2
        SubSubFolder1
    SubFolder3
ParentFolder2
    SubFolder1
ParentFolder3
ParentFolder4
    SubFolder1
        SubSubFolder1
            SubSubSubFolder1
        SubSubFolder2
    SubFolder2
ParentFolder5
    SubFolder1
'''[1:]

def show(seq):
    for row in seq:
        print(row)
    print()

def stripcount(s):
    z = s.lstrip(' ')
    count = len(s) - len(z)
    return z, count

joinpath = os.path.join

def make_dir_tree(dir_tree, root=''):
    ''' Create a directory tree in root from dir_tree,
        which is a list of indented directory names.
    '''
    dir_tree = [stripcount(s) for s in dir_tree]
    #show(dir_tree)

    stack = [root]
    depth = -1
    for dname, count in dir_tree:
        if count > depth:
            depth = count
            stack.append(dname)
        elif count < depth:
            depth = count
            stack.pop()
            stack[-1] = dname
        else:
            stack[-1] = dname

        pathname = joinpath(*stack)
        print(pathname)
        os.mkdir(pathname)


dir_tree = data.splitlines()
show(dir_tree)
make_dir_tree(dir_tree, 'testfolder')
PM 2Ring
  • 54,345
  • 6
  • 82
  • 182
  • 1
    Thank you for putting all that time and effort into answering my question. I'll give it a shot. I really appreciate your help. – Mike Issa Nov 25 '15 at 14:48
  • 1
    @MikeIssa: My pleasure! To be honest, I was more intrigued by the inverse problem. :) That code for creating directory trees might come in handy... – PM 2Ring Nov 25 '15 at 14:58
  • Yes, that was an interesting thing you did there. Creating, or reverse engineering directory paths out of a directory tree of text. Cool stuff... Respect! – Mike Issa Nov 25 '15 at 15:28