--- - name: Create temporary directory on localhost delegate_to: localhost become: false ansible.builtin.tempfile: state: directory register: tempdir - name: Define list of binary extensions set_fact: binary_extensions: - png - jpg - jpeg - gif - pdf - bin - exe - zip - tar - gz - bz2 - xz - mp3 - mp4 - wav - avi - name: Initialize file lists set_fact: text_files: [] binary_files: [] - name: Classify files into text and binary set_fact: text_files: "{{ text_files + [item] if (file_ext not in binary_extensions) else text_files }}" binary_files: "{{ binary_files + [item] if (file_ext in binary_extensions) else binary_files }}" vars: file_ext: "{{ (item.path | splitext | last | regex_replace('^\\.', '')) | lower }}" loop: "{{ lookup('filetree', render_dir) }}" when: item.state == "file" loop_control: label: "{{ item.path }}" - name: Ensure parent directories exist for all files delegate_to: localhost become: false ansible.builtin.file: path: "{{ tempdir.path }}/{{ item.path | dirname }}" state: directory mode: "{{ mode | default('0755') }}" owner: "{{ owner }}" with_filetree: "{{ render_dir }}" when: item.state == "file" - name: Render templates (text files only) delegate_to: localhost become: false ansible.builtin.template: src: "{{ render_dir }}/{{ item.path }}" dest: "{{ tempdir.path }}/{{ item.path }}" mode: "{{ mode | default('0755') }}" owner: "{{ owner }}" loop: "{{ text_files }}" - name: Copy binary files directly delegate_to: localhost become: false ansible.builtin.copy: src: "{{ render_dir }}/{{ item.path }}" dest: "{{ tempdir.path }}/{{ item.path }}" mode: "{{ mode | default('0644') }}" owner: "{{ owner }}" loop: "{{ binary_files }}" - name: Sync rendered and copied files to remote host delegate_to: localhost become: false ansible.builtin.synchronize: src: "{{ tempdir.path }}/" dest: "{{ tempdir.path }}/" owner: true group: true recursive: true - name: Ensure destination exists become: true ansible.builtin.file: path: "{{ destination_dir }}" owner: "{{ owner }}" state: directory - name: Copy files to final destination, preserving ownership stuff become: true ansible.builtin.command: cmd: bash -c 'cp -rp {{ tempdir.path }}/* {{ destination_dir }}/' - name: Remove local temporary directory delegate_to: localhost become: false ansible.builtin.file: path: "{{ tempdir.path }}" state: absent - name: Remove remote temporary directory become: true ansible.builtin.file: path: "{{ tempdir.path }}" state: absent