[python] 파이썬 재귀 폴더 읽기

나는 C ++ / Obj-C 배경을 가지고 있으며 파이썬을 발견하고 있습니다 (약 1 시간 동안 작성했습니다). 폴더 구조에서 텍스트 파일의 내용을 재귀 적으로 읽는 스크립트를 작성 중입니다.

내가 가진 문제는 내가 작성한 코드가 한 폴더 깊이에서만 작동한다는 것입니다. 코드에서 이유를 볼 수 있습니다 ( #hardcoded path), 파이썬에 대한 나의 경험이 새로운 것이므로 파이썬으로 어떻게 나아갈 수 있는지 모르겠습니다.

파이썬 코드 :

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):

다음과 같은 의미가 있습니다.

  • root: “통과”되는 현재 경로
  • subdirs: root디렉토리 유형의 파일
  • files: 디렉토리 이외의 유형의 파일에 root있거나없는 파일subdirs

그리고 os.path.join슬래시로 연결 하는 대신 사용하십시오 ! 문제는 filePath = rootdir + '/' + file최상위 폴더 대신 현재 “걷는”폴더를 연결해야한다는 것입니다. 반드시이어야합니다 filePath = os.path.join(root, file). BTW “파일”은 내장되어 있으므로 일반적으로 변수 이름으로 사용하지 않습니다.

또 다른 문제는 다음과 같은 루프입니다.

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()


답변

Python 3.5 이상을 사용하는 경우 한 줄로 수행 할 수 있습니다.

import glob

for filename in glob.iglob(root_dir + '**/*.txt', recursive=True):
     print(filename)

설명서에 언급 된 바와 같이

재귀가 true 인 경우 패턴 ‘**’은 모든 파일 및 0 개 이상의 디렉토리 및 하위 디렉토리와 일치합니다.

모든 파일을 원한다면

import glob

for filename in glob.iglob(root_dir + '**/*', recursive=True):
     print(filename)


답변

Dave Webb에 동의 os.walk하면 트리의 각 디렉토리에 대한 항목이 생성됩니다. 사실, 당신은 신경 쓰지 않아도됩니다 subFolders.

다음과 같은 코드가 작동합니다.

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())


답변

TL; DR :find -type f 현재 폴더를 포함하여 아래의 모든 폴더에있는 모든 파일을 처리 하는 것과 같습니다 .

for currentpath, folders, files in os.walk('.'):
    for file in files:
        print(os.path.join(currentpath, file))

다른 답변에서 이미 언급했듯이 os.walk()그 대답이 있지만 더 잘 설명 할 수 있습니다. 아주 간단합니다! 이 트리를 살펴 보겠습니다.

docs/
└── doc1.odt
pics/
todo.txt

이 코드로 :

for currentpath, folders, files in os.walk('.'):
    print(currentpath)

currentpath그것을보고있는 현재 폴더입니다. 출력됩니다 :

.
./docs
./pics

따라서 세 개의 폴더가 있기 때문에 세 번 반복 됩니다. 현재 폴더 docs, 및 pics. 모든 루프에서는 변수 채우기 foldersfiles모든 폴더와 파일을. 그들에게 보여 주자 :

for currentpath, folders, files in os.walk('.'):
    print(currentpath, folders, files)

이것은 우리에게 보여줍니다 :

# currentpath  folders           files
.              ['pics', 'docs']  ['todo.txt']
./pics         []                []
./docs         []                ['doc1.odt']

첫 번째 줄에서 우리는 우리가 folder에 .있고, 그것은 두 개의 폴더를 포함 pics하고 docs, 하나의 파일이 있다는 것을 알 수 있습니다 todo.txt. 보시다시피 폴더는 자동으로 되풀이되고 하위 폴더의 파일 만 제공하기 때문에 해당 폴더로 되풀이하기 위해 아무 것도하지 않아도됩니다. 그리고 그 하위 폴더는 (이 예제에는 없지만)

모든 파일을 반복하고 싶다면 다음과 find -type f같습니다.

for currentpath, folders, files in os.walk('.'):
    for file in files:
        print(os.path.join(currentpath, file))

이 결과는 다음과 같습니다.

./todo.txt
./docs/doc1.odt


답변

pathlib라이브러리 파일 작업을위한 정말 좋은 것입니다. 이렇게 Path객체 에 재귀 적 glob을 수행 할 수 있습니다 .

from pathlib import Path

for elem in Path('/path/to/my/files').rglob('*.*'):
    print(elem)


답변

주어진 dir 아래의 모든 경로 목록을 원한다면 ( find .쉘 과 같이 ) :

   files = [
       os.path.join(parent, name)
       for (parent, subdirs, files) in os.walk(YOUR_DIRECTORY)
       for name in files + subdirs
   ]

기본 디렉토리 아래에 파일의 전체 경로 만 포함 시키려면 생략하십시오 + subdirs.


답변

import glob
import os

root_dir = <root_dir_here>

for filename in glob.iglob(root_dir + '**/**', recursive=True):
    if os.path.isfile(filename):
        with open(filename,'r') as file:
            print(file.read())

**/**를 포함하여 모든 파일을 재귀 적으로 가져 오는 데 사용됩니다 directory.

if os.path.isfile(filename)filename변수가 file또는인지 확인하는 데 사용되며 directory파일 인 경우 해당 파일을 읽을 수 있습니다. 여기에 파일을 인쇄하고 있습니다.