40

我想知道是否可以强制os.walk在 python3 中按字母顺序访问目录。例如,这是一个目录和一些将遍历该目录的代码:

ryan:~/bktest$ ls -1 sample
CD01
CD02
CD03
CD04
CD05

--------

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

当 python 代码到达上面的目录时,输出如下:

ryan:~/bktest$ ~/test.py sample
CD03
CD01
CD05
CD02
CD04

我想强制步行按字母顺序访问这些目录,01, 02 ... 05. 在python3 文档中os.walk,它说:

当 topdown 为 True 时,调用者可以就地修改 dirnames 列表(可能使用 del 或 slice 赋值),并且 walk() 只会递归到名称保留在 dirnames 中的子目录;这可以用来修剪搜索,强加特定的访问顺序

这是否意味着我可以强制按字母顺序访问os.walk?如果是这样,怎么做?

4

3 回答 3

52

是的。您在循环中对目录进行排序。

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)
于 2011-07-12T20:47:48.930 回答
6

我知道这已经得到了回答,但我想添加一个小细节,并且在评论中添加不止一行代码是不可靠的。

除了希望对目录进行排序之外,我还希望对文件进行排序,以便我通过“gl”进行的迭代是一致且可预测的。要做到这一点,需要另外一种:

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

并且,受益于更多地了解 Python,一种不同的(更好的)方式:

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()]
于 2018-01-07T16:31:01.077 回答
2

这个答案不是针对这个问题的,而且问题有点不同,但解决方案可以在任何一种情况下使用。考虑拥有这些文件("one1.txt", "one2.txt", "one10.txt"),它们的内容都是 String "default"

我想遍历包含这些文件的目录并在每个文件中找到一个特定的字符串并将其替换为文件名。如果您使用此处和其他问题中已经提到的任何其他方法(例如dirs.sort()andsorted(files)sorted(dirs),结果将是这样的:

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

但我们希望它是:

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

我发现这种按字母顺序更改文件内容的方法:

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)

然后运行这一行:

findReplace(os.getcwd(), "default", "one", "*.xml")
于 2018-07-17T21:33:03.153 回答