You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过单个Ansible任务创建多个目录及各目录内的文件?

单个Ansible Task实现多目录及对应文件创建

需求说明

需根据以下定义的directories变量,创建指定目录并在每个目录下生成对应文件:

directories:
  - directory: dir1
    static_files: 
      files: 
        - file1
        - file2

  - directory: dir2
    static_files: 
      files: 
        - file1
        - file2

当前通过两个file模块任务结合with_subelements实现,但希望合并为单个task完成。现有实现代码:

- name: Creates directories
  file:
    path: "/tmp/{{ item[0].directory }}"
    state: directory
    recurse: yes
    mode: 0755
    owner: user
    group: group
  become: true
  with_subelements: 
    - "{{ directories }}"
    - static_files.files

- name: Creates files
  file:
    path: "/tmp/{{ item[0].directory }}/{{ item[1] }}"
    state: touch
    mode: 0644
    owner: user
    group: group
  become: true
  with_subelements: 
    - "{{ directories }}"
    - static_files.files

期望最终生成的文件结构:

/tmp/dir1/file1
/tmp/dir1/file2
/tmp/dir2/file1
/tmp/dir2/file2

解决方案

方案1:使用copy模块一键完成(推荐)

利用copy模块创建空文件的特性,它会自动创建不存在的父目录,同时通过directory_mode参数指定父目录的权限,只需单个task即可完成所有操作:

- name: Create directories and files
  ansible.builtin.copy:
    dest: "/tmp/{{ item[0].directory }}/{{ item[1] }}"
    content: ""  # 创建空文件
    mode: 0644    # 文件权限
    owner: user
    group: group
    directory_mode: 0755  # 自动创建的父目录权限
  become: true
  with_subelements:
    - "{{ directories }}"
    - static_files.files

方案2:生成路径列表后用file模块循环处理

如果偏好使用file模块,可以先通过变量生成包含所有目录和文件的路径列表,再在单个task中循环处理:

- name: Create directories and files
  ansible.builtin.file:
    path: "{{ item.path }}"
    state: "{{ item.state }}"
    mode: "{{ item.mode }}"
    owner: user
    group: group
  become: true
  loop: >-
    {{
      # 生成目录路径项
      directories | map('extract', ['directory']) | map('regex_replace', '^(.*)$', '/tmp/\\1') | map('community.general.dict_kv', 'path') | map('combine', {'state': 'directory', 'mode': '0755'}) | list +
      # 生成文件路径项
      directories | subelements('static_files.files') | map('regex_replace', '^\\[(.*), (.*)\\]$', '/tmp/\\1/\\2') | map('community.general.dict_kv', 'path') | map('combine', {'state': 'touch', 'mode': '0644'}) | list
    }}

注意:此方案依赖community.general集合中的dict_kv过滤器,若未安装可先执行ansible-galaxy collection install community.general。

内容的提问来源于stack exchange,提问作者ayuuk ja'ay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 06:35:32