如何在dbt宏中用Jinja遍历文件夹并获取文件名?
在dbt宏中获取文件夹文件名的实现方法
Jinja本身确实没有直接访问文件系统的能力,dbt默认的Jinja环境也做了限制,避免安全风险和跨环境不一致问题。但可以通过以下两种方式实现需求:
1. 借助dbt的Python能力(推荐)
dbt 1.0+支持Python宏或在Jinja宏中通过run_python执行Python代码,直接操作文件系统:
方式一:使用run_python在Jinja宏中直接实现
{% macro list_folder_files(folder_path) %} {% set safe_path = folder_path | replace("'", "\\'") %} {% set python_code %} import os from os.path import isfile, join # 只获取当前文件夹下的文件(不递归子文件夹) file_list = [f for f in os.listdir('{{ safe_path }}') if isfile(join('{{ safe_path }}', f))] return file_list {% endpython_code %} {% set file_array = run_python(python_code) %} {{ return(file_array) }} {% endmacro %}
调用示例:
{% set my_files = list_folder_files(project_dir ~ '/models/staging') %} {% do log('Files found: ' ~ my_files, info=True) %}
方式二:编写独立Python宏
在macros文件夹下创建.py文件(比如file_utils.py):
import os from os.path import isfile, join def list_files(folder_path, recursive=False): file_list = [] if recursive: for root, _, files in os.walk(folder_path): for file in files: file_list.append(join(root, file)) else: file_list = [f for f in os.listdir(folder_path) if isfile(join(folder_path, f))] return file_list
然后在Jinja宏中调用:
{% macro get_files(folder, recursive=False) %} {% set file_array = modules.file_utils.list_files(folder, recursive) %} {{ return(file_array) }} {% endmacro %}
2. 利用dbt内置元数据(仅适用于项目内资源)
如果你要获取的是dbt项目本身的资源文件(比如模型、宏、种子文件),不需要访问文件系统,直接用dbt的graph变量即可获取已加载的资源元数据:
{% macro get_model_filenames() %} {% set model_files = [] %} {% for node in graph.nodes.values() %} {% if node.resource_type == 'model' %} {% do model_files.append(node.original_file_name) %} {% endif %} {% endfor %} {{ return(model_files) }} {% endmacro %}
注意事项
- 路径建议结合dbt内置的
project_dir变量拼接,确保跨环境路径一致; - 运行dbt的用户需要拥有目标文件夹的读取权限;
- 跨平台开发时,优先用
os.path.join处理路径分隔符,避免Windows/Linux兼容性问题。
内容的提问来源于stack exchange,提问作者Damir
相关产品推荐
相关产品推荐

