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

当前回答

操作系统。Walk默认情况下执行递归遍历。对于每个dir,它从根目录开始生成一个3元组(dirpath, dirnames, filename)

from os import walk
from os.path import splitext, join

def select_files(root, files):
    """
    simple logic here to filter out interesting files
    .py files in this example
    """

    selected_files = []

    for file in files:
        #do concatenation here to get full path 
        full_path = join(root, file)
        ext = splitext(file)[1]

        if ext == ".py":
            selected_files.append(full_path)

    return selected_files

def build_recursive_dir_tree(path):
    """
    path    -    where to begin folder scan
    """
    selected_files = []

    for root, dirs, files in walk(path):
        selected_files += select_files(root, files)

    return selected_files

其他回答

我认为问题在于你没有处理os的输出。正确的走路。

首先,改变:

filePath = rootdir + '/' + file

to:

filePath = root + '/' + file

Rootdir是固定的起始目录;Root是os.walk返回的目录。

其次,您不需要缩进您的文件处理循环,因为对每个子目录运行这个没有意义。您将获得每个子目录的根集。您不需要手动处理子目录,除非您想对目录本身做一些事情。

同意Dave Webb的观点。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())

如果你更喜欢(几乎)联机:

from pathlib import Path

lookuppath = '.' #use your path
filelist = [str(item) for item in Path(lookuppath).glob("**/*") if Path(item).is_file()]

在这种情况下,您将得到一个列表,其中仅包含递归位于lookppath下的所有文件的路径。 如果没有str(),你将得到PosixPath()添加到每个路径。

如果你使用的是Python 3.5或更高版本,你可以在一行内完成。

import glob

# root_dir needs a trailing slash (i.e. /root/dir/)
for filename in glob.iglob(root_dir + '**/*.txt', recursive=True):
     print(filename)

正如文档中提到的

如果递归为true,模式'**'将匹配任何文件以及零个或多个目录和子目录。

如果你想要每个文件,你可以使用

import glob

for filename in glob.iglob(root_dir + '**/**', recursive=True):
     print(filename)
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())

**/**用于递归地获取所有文件,包括目录。

如果os.path.isfile(filename)用于检查filename变量是文件还是目录,如果是文件,则可以读取该文件。 我正在打印文件。