У меня есть 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()
Убедитесь, что вы понимаете три возвращаемых значения 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()
Согласитесь с Дэйвом Уэббом, 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())
Я думаю, проблема в том, что вы неправильно обрабатываете вывод os.walk
.
Во-первых, измените:
filePath = rootdir + '/' + file
на:
filePath = root + '/' + file
rootdir
- ваш фиксированный начальный каталог; root
- это каталог, возвращаемый os.walk
.
Во-вторых, вам не нужно делать отступы для цикла обработки файлов, поскольку нет смысла запускать это для каждого подкаталога. Вы получите root
для каждого подкаталога. Вам не нужно обрабатывать подкаталоги вручную, если вы не хотите что-то делать с самими каталогами.
использовать 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()