如何使用 os.walk 只列出文本文件

How to use os.walk to only list text files

This question was similar in addressing hidden filetypes. I am struggling with a similar problem because I need to process only text containing files in folders that have many different filetypes- pictures, text, music. I am using os.walk which lists EVERYTHING, including files without an extension-like Icon files. I am using linux and would be satisfied to filter for only txt files. One way is too check the filename extension and this post 很好地解释了它是如何完成的。

但这仍然会留下错误标记的文件或没有扩展名的文件。有十六进制值可以唯一标识文件类型,称为幻数或文件签名。 here and here Unfortunately, magic numbers do not exist for text files (see here)。

我想出的一个策略是通过字典查找来解析第一串字符以确保它们是单词(我只处理英文文本)然后只进行全文处理如果那就是 true.This 方法似乎相当繁重和昂贵(为每个文件做一堆字典查找)。另一种方法是简单地查找单词 'the',它在数据文件中不太可能出现,但在文本文件中很常见。但是漏报会导致我丢失要处理的文本文件。我试着向 google 询问没有 'the' 一词的最长文本,但没有成功。

我不知道这是否是提出此类问题的合适论坛 - 这几乎是 AI 而非计算机的问题 science/coding。它不像乱码检测那么困难。这些文本在语义或句法上可能不正确——它们可能只是像仓库库存那样的单词,但也可能是散文和诗歌。我只是不想处理可能是字节码、源代码或不是英语单词的字母数字字符集合的文件。

您可以使用 Python 的 mimetypes 库来检查文件是否为纯文本文件。

import os
import mimetypes

for dirpath, dirnames, filenames in os.walk('/path/to/directory'):
    for filename in filenames:
        if mimetypes.guess_type(filename)[0] == 'text/plain':
            print(os.path.join(dirpath, filename))

UPDATE: 由于 mimetypes 库使用文件扩展名来确定文件类型,因此它不是很可靠,特别是你提到有些文件被错误标记或没有扩展名。

对于这些情况,您可以使用 magic 库(遗憾的是它不在标准库中)。

import os
import magic

mime = magic.Magic(mime=True)
for dirpath, dirnames, filenames in os.walk('/path/to/directory'):
    for filename in filenames:
        fullpath = os.path.join(dirpath, filename)
        if mime.from_file(fullpath) == 'text/plain':
            print(fullpath)

更新 2:上述解决方案不会捕获您认为 "plaintext" 的文件(例如 XML 文件、源文件等)。以下解决方案应该适用于这些情况:

import os
import magic

for dirpath, dirnames, filenames in os.walk('/path/to/directory'):
    for filename in filenames:
        fullpath = os.path.join(dirpath, filename)
        if 'text' in magic.from_file(fullpath):
            print(fullpath)

让我知道这些是否适合您。

一个很好的启发式方法是在文件的开头查找空字节。文本文件通常没有它们,而二进制文件通常有很多。下面检查前 1K 字节是否不包含空值。您当然可以调整要读取的文件的多少:

#!python3
import os

def textfiles(root):
    for path,dirs,files in os.walk(root):
        for file in files:
            fullname = os.path.join(path,file)
            with open(fullname,'rb') as f:
                data = f.read(1024)
            if not 0 in data:
                yield fullname

for file in textfiles('.'):
    print(file)