Итерация через каталоги с помощью Python
Мне нужно выполнить итерацию через подкаталоги данного каталога и поиск файлов. Если я получаю файл, я должен его открыть и изменить содержимое и заменить его на собственные строки.
Я пробовал это:
import os
rootdir ='C:/Users/sid/Desktop/test'
for subdir, dirs, files in os.walk(rootdir):
for file in files:
f=open(file,'r')
lines=f.readlines()
f.close()
f=open(file,'w')
for line in lines:
newline = "No you are not"
f.write(newline)
f.close()
но я получаю сообщение об ошибке. Что я делаю не так?
Ответы
Ответ 1
Фактическая прогулка по каталогам работает так, как вы ее закодировали. Если вы замените содержимое внутреннего цикла простым инструктором print
, вы увидите, что каждый файл найден:
import os
rootdir = 'C:/Users/sid/Desktop/test'
for subdir, dirs, files in os.walk(rootdir):
for file in files:
print os.path.join(subdir, file)
Если вы все еще получаете ошибки при запуске вышеуказанного, предоставьте сообщение об ошибке.
Ответ 2
Другой способ вернуть все файлы в подкаталогах - использовать модуль pathlib
, представленный в Python 3.4, который обеспечивает объектно-ориентированный подход к обработке путей в файловой системе (Pathlib также доступен в Python 2.7 через модуль pathlib2 в PyPi):
from pathlib import Path
rootdir = Path('C:/Users/sid/Desktop/test')
# Return a list of regular files only, not directories
file_list = [f for f in rootdir.glob('**/*') if f.is_file()]
# For absolute paths instead of relative the current dir
file_list = [f for f in rootdir.resolve().glob('**/*') if f.is_file()]
Начиная с Python 3.5, модуль glob
также поддерживает рекурсивный поиск файлов:
import os
from glob import iglob
rootdir_glob = 'C:/Users/sid/Desktop/test/**/*' # Note the added asterisks
# This will return absolute paths
file_list = [f for f in iglob('**/*', recursive=True) if os.path.isfile(f)]
file_list
любого из вышеперечисленных подходов может быть повторен без необходимости во вложенном цикле:
for f in file_list:
print(f) # Replace with desired operations
Ответ 3
Начиная с 2019 года, glob.iglob(path/**, recursive=True)
представляется наиболее питоническим решением, т.е.
import glob, os
for filename in glob.iglob('/pardadox-music/**', recursive=True):
if os.path.isfile(filename): # filter dirs
print(filename)
Выход:
/pardadox-music/modules/her1.mod
/pardadox-music/modules/her2.mod
...
Примечания:
1 - glob.iglob
glob.iglob(pathname, recursive=False)
Вернуть итератор, который выдает те же значения, что и glob()
, фактически не сохраняя их все одновременно.
2 - Если рекурсивным является True
, шаблон '**'
будет соответствовать любым файлам и
ноль или более directories
и subdirectories
.
3 - Если каталог содержит файлы, начинающиеся с .
, они не будут сопоставлены по умолчанию. Например, рассмотрим каталог, содержащий card.gif
и .card.gif
:
>>> import glob.
>>> glob.glob('*.gif')
['card.gif']
glob.glob('.c*')
[ '.Card.gif']
,
Ответ 4
for subdir, dirs, files in os.walk(rootdir):
os.chdir(rootdir) # >>>>>>>>>>>>>>>>>>>>>>>>>> Pls add this line and try.
for file in files:
print file
f=open(file,'r')
lines=f.readlines()