Ответ 1
Да. Вы сортируете dirs в цикле.
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)
Я хотел бы знать, можно ли заставить 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
говорится:
Когда превышение равно True, вызывающий может изменить список имен dirnames на месте (возможно, используя назначение del или slice), а walk() будет только перезаписывать в подкаталоги, имена которых остаются в dirnames; это можно использовать для обрезки поиска, наложения определенного порядка посещения
Означает ли это, что я могу навязать алфавитный заказ на os.walk
? Если да, то как?
Да. Вы сортируете dirs в цикле.
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)
Я знаю, что на этот вопрос уже дан ответ, но я хотел добавить одну маленькую деталь, и добавление более чем одной строки кода в комментариях - это просто замечательно.
В дополнение к желанию сортировки каталогов я также хотел отсортировать файлы так, чтобы моя итерация по "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
[print(p) for p in sorted(Path(gl['pwd']).glob('**/*')) if p.is_dir()]
Этот ответ не является специфическим для этого вопроса, и проблема немного отличается, но решение может быть использовано в любом случае. Рассмотрим наличие этих файлов ("one1.txt"
, "one2.txt"
, "one10.txt"
), и содержимое всех из них является строкой "default"
:
Я хочу пройтись по каталогу, содержащему эти файлы, найти конкретную строку в каждом файле и заменить его именем файла. Если вы используете любые другие методы, которые уже упоминались здесь и в других вопросах (например, dirs.sort()
и dirs.sort()
sorted(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 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")