Can I force python3's os.walk to visit directories in alphabetical order? how?

一个人想着一个人 提交于 2019-11-28 08:59:00

Yes. You sort dirs in the loop.

def main_work_subdirs(gl):
    for root, dirs, files in os.walk(gl['pwd']):
        dirs.sort()
        if root == gl['pwd']:
            for d2i in dirs:
                print(d2i)

I know this has already been answered but I wanted to add one little detail and adding more than a single line of code in the comments is wonky.

In addition to wanting the directories sorted I also wanted the files sorted so that my iteration through "gl" was consistent and predictable. To do this one more sort was required:

for root, dirs, files in os.walk(gl['pwd']):
  dirs.sort()
  for filename in sorted(files):
    print(os.path.join(root, filename))

And, with benefit of learning more about Python, a different (better) way:

from pathlib import Path
# Directories, per original question.
[print(p) for p in sorted(Path(gl['pwd']).glob('**/*')) if p.is_dir()]
# Files, like I usually need.
[print(p) for p in sorted(Path(gl['pwd']).glob('**/*')) if p.is_file()]

This answer is not specific to this question and the problem is a little different but the solution can be used in either case. Consider having these files ("one1.txt", "one2.txt", "one10.txt") and the content of all of them is a String "default":

I want to loop through a directory that contains these files and find a specific String in every file and replace it with the name of the file. If you use any other methods which have already mentioned here and in other questions (like dirs.sort() and sorted(files) and sorted(dirs), the result will be something like this:

"one1.txt"--> "one10"
"one2.txt"--> "one1"
"one10.txt" --> "one2"

But we want it to be:

"one1.txt"--> "one1"
"one2.txt"--> "one2"
"one10.txt" --> "one10"

I found this method which changes file content alphabetically:

import re, os, fnmatch

def atoi(text):
    return int(text) if text.isdigit() else text

def natural_keys(text):
    '''
    alist.sort(key=natural_keys) sorts in human order
    http://nedbatchelder.com/blog/200712/human_sorting.html
    (See Toothy's implementation in the comments)
    '''
    return [ atoi(c) for c in re.split('(\d+)', text) ]

def findReplace(directory, find, replace, filePattern):
    count = 0
    for path, dirs, files in sorted(os.walk(os.path.abspath(directory))):
        dirs.sort()
        for filename in sorted(fnmatch.filter(files, filePattern), key=natural_keys):
            count = count +1
            filepath = os.path.join(path, filename)
            with open(filepath) as f:
                s = f.read()
            s = s.replace(find, replace+str(count)+".png")
            with open(filepath, "w") as f:
                f.write(s)

Then run this line:

findReplace(os.getcwd(), "default", "one", "*.xml")
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!