Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python递归文件夹读取_Python_Scripting_File Io - Fatal编程技术网

Python递归文件夹读取

Python递归文件夹读取,python,scripting,file-io,Python,Scripting,File Io,我有C++/Obj-C的背景,我刚刚发现Python(写了大约一个小时)。 我正在编写一个脚本,以递归方式读取文件夹结构中文本文件的内容 我的问题是,我编写的代码只适用于一个文件夹深度。我可以从代码中看出原因(请参见#硬编码路径),我只是不知道如何继续使用Python,因为我对Python的体验是全新的 Python代码: import os import sys rootdir = sys.argv[1] for root, subFolders, files in os.walk(roo

我有C++/Obj-C的背景,我刚刚发现Python(写了大约一个小时)。 我正在编写一个脚本,以递归方式读取文件夹结构中文本文件的内容

我的问题是,我编写的代码只适用于一个文件夹深度。我可以从代码中看出原因(请参见
#硬编码路径
),我只是不知道如何继续使用Python,因为我对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
的输出

第一,改变:

filePath = rootdir + '/' + file
致:

rootdir
是您的固定起始目录<代码>根目录是由
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()

确保您理解操作系统的三个返回值。walk:

for root, subdirs, files in os.walk(rootdir):
具有以下含义:

  • 根目录
    :当前路径为“遍历”
  • 子目录
    :类型目录的
    根目录中的文件
  • 文件
    :目录以外类型的
    根目录中的文件(不在
    子目录中)
请使用
os.path.join
而不是用斜杠连接!您的问题是
filePath=rootdir+'/'+file
-您必须连接当前的“walk”文件夹,而不是最上面的文件夹。所以必须是
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()

同意Dave Webb的意见,
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
默认情况下执行递归遍历。对于每个dir,从根开始,它产生一个3元组(dirpath、dirname、filename)

从操作系统导入漫游
从os.path导入拆分文本,加入
def选择_文件(根,文件):
"""
这里的简单逻辑可以过滤出感兴趣的文件
本例中的.py文件
"""
选定的_文件=[]
对于文件中的文件:
#在这里进行连接以获得完整路径
完整路径=连接(根,文件)
ext=splitext(文件)[1]
如果ext==“.py”:
选定的\u文件。追加(完整\u路径)
返回所选的\u文件
def构建递归目录树(路径):
"""
路径-开始文件夹扫描的位置
"""
选定的_文件=[]
对于根目录、目录、漫游中的文件(路径):
选定的_文件+=选择_文件(根,文件)
返回所选的\u文件
试试这个:

import os
import sys

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

    for file in os.listdir(root):

        filePath = os.path.join(root, file)

        if os.path.isdir(filePath):
            pass

        else:
            f = open (filePath, 'r')
            # Do Stuff

如果您使用的是Python3.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)
如报告中所述

如果recursive为true,则模式“**”将匹配任何文件以及零个或多个目录和子目录

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

import glob

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

如果需要给定目录下所有路径的平面列表(如shell中的
find.
):

要仅包括基本目录下文件的完整路径,请省略
+子目录

导入全局
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())
导入操作系统 根目录= 对于glob.iglob(root_dir+'**/**',recursive=True)中的文件名: 如果os.path.isfile(文件名): 打开(文件名,'r')作为文件: 打印(file.read())
***/***
用于递归获取所有文件,包括
目录

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

TL;DR:这相当于
查找-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
。在每个循环中,它用所有文件夹和文件填充变量
文件夹
文件
。让我们向他们展示:

for currentpath, folders, files in os.walk('.'):
    print(currentpath, folders, files)
这告诉我们:

# currentpath  folders           files
.              ['pics', 'docs']  ['todo.txt']
./pics         []                []
./docs         []                ['doc1.odt']
所以在第一行中,我们看到我们在文件夹
,它包含两个文件夹,即
pics
docs
,还有一个文件,即
todo.txt
。您不必做任何事情就可以递归到这些文件夹中,因为正如您所看到的,它会自动递归,并只提供任何子文件夹中的文件。以及它的任何子文件夹(尽管示例中没有这些子文件夹)

如果您只想循环浏览所有文件(相当于
查找-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
库非常适合处理文件。您可以像这样在
路径
对象上执行递归全局搜索

from pathlib import Path

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

我发现以下是最简单的

从全局导入全局
导入操作系统
files=[f表示glob中的f('rootdir/**',recursive=True),如果os.path.isfile(f)]
使用
glob('some/path/**',recursive=True)
获取所有文件,但也包括目录名。添加
如果os.path.isfile(f)
条件仅将此列表筛选到现有文件

如果您喜欢(几乎)一行:

from pathlib import Path

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

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

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

root_dir = "C:\\Users\\Scott\\" # Don't forget trailing (last) slashes    
for filename in glob.iglob(root_dir + '**/*.jpg', recursive=True):
     print(filename)
     # do stuff