Python рекурсивное чтение папки

У меня есть C++/Obj-C фон, и я просто обнаруживаю Python (запись его приблизительно в течение часа). Я пишу сценарий для рекурсивного чтения содержания текстовых файлов в структуре папок.

Проблемой, которую я имею, является код, который я написал, будет только работать на одну папку глубоко. Я вижу, почему в коде (см. #hardcoded path), я просто не знаю, как я могу продвинуться с Python, так как мой опыт с ним является только совершенно новым.

Код Python:

import os
import sys

rootdir = sys.argv[1]

for root, subFolders, files in os.walk(rootdir):

    for folder in subFolders:
        outfileName = rootdir + "/" + folder + "/py-outfile.txt" # hardcoded path
        folderOut = open( outfileName, 'w' )
        print "outfileName is " + outfileName

        for file in files:
            filePath = rootdir + '/' + file
            f = open( filePath, 'r' )
            toWrite = f.read()
            print "Writing '" + toWrite + "' to" + filePath
            folderOut.write( toWrite )
            f.close()

        folderOut.close()
188
задан Bhavesh Gangani 17 May 2015 в 10:04
поделиться

4 ответа

Убедитесь, что вы понимаете три возвращаемых значения os.walk :

for root, subdirs, files in os.walk(rootdir):

имеет следующее значение:

  • корень : Текущий путь который "проходит через"
  • подкаталоги : файлы в корне типа каталог
  • файлы : файлы в корневом (не в подкаталогах ) типа, отличного от каталога

И используйте os.path.join вместо конкатенации с косой чертой! Ваша проблема - filePath = rootdir + '/' + file - вы должны объединить текущую "просматриваемую" папку вместо самой верхней папки. Это должно быть filePath = os.path.join (root, file) . Кстати, «файл» является встроенным, поэтому вы обычно не используете его в качестве имени переменной.

Другой проблемой являются ваши циклы, которые должны выглядеть, например, следующим образом:

import os
import sys

walk_dir = sys.argv[1]

print('walk_dir = ' + walk_dir)

# If your current working directory may change during script execution, it's recommended to
# immediately convert program arguments to an absolute path. Then the variable root below will
# be an absolute path as well. Example:
# walk_dir = os.path.abspath(walk_dir)
print('walk_dir (absolute) = ' + os.path.abspath(walk_dir))

for root, subdirs, files in os.walk(walk_dir):
    print('--\nroot = ' + root)
    list_file_path = os.path.join(root, 'my-directory-list.txt')
    print('list_file_path = ' + list_file_path)

    with open(list_file_path, 'wb') as list_file:
        for subdir in subdirs:
            print('\t- subdirectory ' + subdir)

        for filename in files:
            file_path = os.path.join(root, filename)

            print('\t- file %s (full path: %s)' % (filename, file_path))

            with open(file_path, 'rb') as f:
                f_content = f.read()
                list_file.write(('The file %s contains:\n' % filename).encode('utf-8'))
                list_file.write(f_content)
                list_file.write(b'\n')

Если вы не знали, оператор with для файлов является сокращением:

with open('filename', 'rb') as f:
    dosomething()

# is effectively the same as

f = open('filename', 'rb')
try:
    dosomething()
finally:
    f.close()
309
ответ дан 23 November 2019 в 05:42
поделиться

Согласитесь с Дэйвом Уэббом, os.walk даст элемент для каждого каталога в дереве. На самом деле вам просто не нужно заботиться о вложенных папках .

Такой код должен работать:

import os
import sys

rootdir = sys.argv[1]

for folder, subs, files in os.walk(rootdir):
    with open(os.path.join(folder, 'python-outfile.txt'), 'w') as dest:
        for filename in files:
            with open(os.path.join(folder, filename), 'r') as src:
                dest.write(src.read())
35
ответ дан 23 November 2019 в 05:42
поделиться

Я думаю, проблема в том, что вы неправильно обрабатываете вывод os.walk .

Во-первых, измените:

filePath = rootdir + '/' + file

на:

filePath = root + '/' + file

rootdir - ваш фиксированный начальный каталог; root - это каталог, возвращаемый os.walk .

Во-вторых, вам не нужно делать отступы для цикла обработки файлов, поскольку нет смысла запускать это для каждого подкаталога. Вы получите root для каждого подкаталога. Вам не нужно обрабатывать подкаталоги вручную, если вы не хотите что-то делать с самими каталогами.

0
ответ дан 23 November 2019 в 05:42
поделиться

использовать os.path.join() для построения ваших путей - Это аккуратнее:

import os
import sys
rootdir = sys.argv[1]
for root, subFolders, files in os.walk(rootdir):
    for folder in subFolders:
        outfileName = os.path.join(root,folder,"py-outfile.txt")
        folderOut = open( outfileName, 'w' )
        print "outfileName is " + outfileName
        for file in files:
            filePath = os.path.join(root,file)
            toWrite = open( filePath).read()
            print "Writing '" + toWrite + "' to" + filePath
            folderOut.write( toWrite )
        folderOut.close()
3
ответ дан 23 November 2019 в 05:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: