--- - name: Create temporary directory on localhost delegate_to: localhost become: false ansible.builtin.tempfile: state: directory register: tempdir - 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: Check if each file is text or binary delegate_to: localhost become: false ansible.builtin.command: cmd: file --mime-type "{{ item.src }}" register: file_type_check changed_when: false with_filetree: "{{ render_dir }}" when: item.state == "file" loop_control: label: "{{ item.path }}" - name: Separate text and binary files set_fact: text_files: >- {{ file_type_check.results | selectattr('stdout', 'defined') | selectattr('stdout', 'search', '^.*: text/') | map(attribute='item') | list }} binary_files: >- {{ file_type_check.results | selectattr('stdout', 'defined') | rejectattr('stdout', 'search', '^.*: text/') | map(attribute='item') | list }} - name: Render templates (text files only) delegate_to: localhost become: false ansible.builtin.template: src: "{{ item.src }}" 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: "{{ item.src }}" 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 ansible.builtin.file: path: "{{ destination_dir }}" owner: "{{ owner }}" state: directory - name: Copy files to final destination, preserving ownership stuff 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 ansible.builtin.file: path: "{{ tempdir.path }}" state: absent