readfiles:批量读取指定文件夹中特定扩展名的所有文本文件

📦 命令概述

最近遇到了一些需要批量把某个文件夹里面所有的文本文件读取的需求,读取结果包含两个变量,第一个变量是文件名称,第二个变量是每个文本文件的内容。于是就编写了这个命令:readfiles。

readfiles 是一个强大的 Stata 命令,用于批量读取指定文件夹中特定扩展名的所有文件,并将每个文件的内容存储为数据集中的观测值。特别适合处理文本文件、日志文件、代码文件等。

🔧 安装方法

net install readfiles.pkg, from("readfiles.pkg 文件所在的文件夹路径")

验证安装

which readfiles
help readfiles

📁 生成示例数据

首先让我们创建一些示例文件来测试命令:

特别需要注意,文件夹名称里面不要有空格,文件夹路径名称不需要使用双引号。

*- 创建测试文件夹
capture mkdir test_files
cd test_files

*- 创建第一个示例文本文件
file open myfile using "example1.txt", write text replace
file write myfile "这是第一个示例文件" _n
file write myfile "包含一些文本内容:`特殊字符`处理" _n
file write myfile "第三行内容"
file close myfile

*- 创建第二个示例文本文件
file open myfile using "example2.txt", write text replace
file write myfile "第二个文件" _n
file write myfile "文件结束"
file close myfile

*- 创建日志文件
file open myfile using "data.log", write text replace
file write myfile "日志文件开始" _n
file write myfile "日志结束"
file close myfile

*- 回到原始目录
cd ..

🚀 基本使用方法

1. 读取文本文件

readfiles test_files, ext(txt) replace

*- 2. 查看生成的数据集结构
describe

*> Contains data
*> Observations: 1
*> Variables: 2
*> -----------------------------------------------------------------------------------------
*> Variable Storage Display Value
*> name type format label Variable label
*> -----------------------------------------------------------------------------------------
*> filename str19 %19s
*> content str31 %31s
*> -----------------------------------------------------------------------------------------
*> Sorted by:
*> Note: Dataset has changed since last saved.

*- 3. 查看前几行数据
list in 1/2

2. 读取日志文件

readfiles test_files, ext(log) replace

3. 使用调试模式

readfiles test_files, ext(txt) debug replace

📊 查看结果

运行命令后,查看生成的数据集:

*- 查看数据结构
describe

*- 查看前几行数据
list in 1/2

*- 查看文件内容
browse

输出示例:

*>     +---------------------------------------------------------------+
*> | filename | content |
*> |---------------------------------------------------------------|
*> 1. | test_files/example1.txt | 这是第一个示例文件 |
*> | | 包含一些文本内容:'特殊字符'处理 |
*> | | 第三行内容 |
*> |---------------------------------------------------------------|
*> 2. | test_files/example2.txt | 第二个文件 |
*> | | 更多内容:'测试反引号'转义 |
*> | | 文件结束 |
*> +---------------------------------------------------------------+

🔍 高级功能

1. 获取返回结果

readfiles test_files, ext(txt) replace
ret list

*- 查看读取的文件数量
di "读取了 " r(filecount) " 个文件"
*> 读取了 2 个文件

*- 查看文件列表
di "文件列表: " r(filelist)
*> 文件列表: "example1.txt" "example2.txt"

2. 处理特殊字符

命令会自动将文件中的反引号 (`) 转换为单引号 (‘),避免 Stata 解释错误。

3. 批量处理多种文件类型

*- 批量处理多种文件类型
cap mkdir "res"
foreach ext in txt log {
capture readfiles test_files, ext(`ext') replace
if _rc == 0 {
ren filename filename0
save "res/`ext'_files.dta", replace
di "已保存 `ext' 文件结果"
}
}

*- 再使用 appendall 就可以合并了
appendall res, clear

⚠️ 注意事项

  1. 文件编码:确保文件使用 UTF-8 或 Stata 支持的编码格式
  2. 内存限制:大文件可能会消耗大量内存
  3. 文件权限:确保有读取目标文件的权限
  4. 特殊字符:反引号会被自动转义为单引号
  5. 文件名称:readfiles 命令后面的文件夹名称不需要加双引号,也意味着文件夹的名字里面不能含有空格、括号等特殊符号

🛠️ 故障排除

常见错误及解决方法:

*- 错误:数据集已存在
readfiles folder, ext(txt) // 需要添加 replace 选项
readfiles folder, ext(txt) replace

*- 错误:找不到文件
readfiles wrong_path, ext(txt) // 检查路径是否正确

*- 错误:无效的文件扩展名
readfiles folder, ext(123) // 使用有效的扩展名

*- 错误:文件夹使用了双引号
readfiles "folder", ext(txt) replace // 错误
readfiles folder, ext(txt) replace // 正确

📋 命令语法总结

readfiles folder_path, ext(string) [replace debug]
  • 必需参数:
  • 可选选项:

命令源代码

为了便于大家更清楚地了解 readfiles 命令,我还提供了该命令的源代码,感兴趣的小伙伴可以自行学习。

*! 读取指定文件夹中特定类型的所有文件,版本 4.0(增强型特殊符号处理)
*! 作者:微信公众号 RStata
*! 日期:2025年8月22日
*! 语法:readfiles 文件夹路径, ext(文件扩展名) [replace debug]

program define readfiles, rclass
version 15.1
syntax anything(name=folder), ext(string) [replace debug]

* 检查是否要替换现有数据集
if "`replace'" == "" & _N > 0 {
di as error "数据集已存在,请使用 replace 选项替换"
exit 1
}

* 确保文件夹路径以斜杠结尾
local last_char = substr("`folder'", -1, 1)
if "`last_char'" != "/" & "`last_char'" != "\" {
local folder "`folder'/"
}

* 获取指定文件夹中特定类型的所有文件
local files : dir `"`folder'"' files "*.`ext'"

* 如果没有找到文件
if `"`files'"' == "" {
di as error "在文件夹 `folder' 中没有找到 .`ext' 类型的文件"
exit 2
}

* 创建新数据集
clear
qui {
set obs 0
gen filename = ""
gen content = ""
}
* 循环读取每个文件
local i = 1
foreach file in `files' {
di as text "正在读取文件: `file'"

* 使用临时文件处理特殊字符
tempfile tmpfile
tempfile tmpfilefilter
local fullpath "`folder'`file'"

* 将文件内容复制到临时文件,同时转义`符号
qui copy "`fullpath'" "`tmpfile'", replace

* 使用filefilter命令进行更可靠的替换
qui filefilter "`tmpfile'" "`tmpfilefilter'", from("`") to("'") replace

* 从过滤后的临时文件读取内容
local content = fileread("`tmpfilefilter'")

* 调试模式:显示处理后的内容前100个字符
if "`debug'" != "" {
di as text "处理后的内容预览: " substr(`"`content'"', 1, 100) "..."
}

* 将文件名和内容存入数据集
qui {
set obs `i'
replace filename = "`fullpath'" in `i'
replace content = `"`content'"' in `i'
}

local i = `i' + 1
}

ret scalar filecount = `=`i'-1'
ret local filelist = `"`files'"'

* 显示结果信息
di as result "成功读取了 `=`i'-1' 个 .`ext' 类型的文件"
di as result "数据集包含变量: filename (文件名) 和 content (文件内容)"
di as text "注意:文件中的反引号已被转义为单引号"
end

点击这里跳转到 RStata 短书平台获取附件:readfiles:批量读取指定文件夹中特定扩展名的所有文本文件

评论