When working with Ansible's copy
module, you might need to copy an entire directory while excluding specific files or subdirectories. The official documentation doesn't explicitly cover this scenario, which can be frustrating when dealing with directories containing hundreds of files.
with_fileglob Loop /h2>
One approach is to combine the copy
module with a with_fileglob
loop to selectively copy files:
- name: Copy all files except one
copy:
src: "{{ item }}"
dest: /destination/path/
with_fileglob:
- "/source/path/*"
- "!/source/path/excluded_file"
find Module /h2>
For more complex exclusion patterns, you can use the find
module first to generate a file list:
- name: Find all files except the one to exclude
find:
paths: /source/path
patterns: "*"
excludes: "excluded_file"
recurse: yes
register: files_to_copy
- name: Copy the filtered files
copy:
src: "{{ item.path }}"
dest: "/destination/path/{{ item.path | basename }}"
loop: "{{ files_to_copy.files }}"
synchronize /h2>
For large directories, the synchronize
module (which uses rsync) might be more efficient:
- name: Sync directory with exclusion
synchronize:
src: /source/path/
dest: /destination/path/
exclude: excluded_file
When you need to exclude multiple patterns, you can use lists:
- name: Exclude multiple files
synchronize:
src: /source/path/
dest: /destination/path/
exclude:
- "*.tmp"
- "*.log"
- "secret_file"
For directories with thousands of files, the synchronize
approach will generally be faster than iterating with copy
. However, remember that synchronize
requires rsync to be installed on both the control and target machines.
When working with Ansible's copy
module, you might encounter scenarios where you need to recursively copy all contents of a directory except specific files or subdirectories. The official documentation doesn't explicitly cover this exclusion pattern, especially when dealing with large directory structures where manual enumeration isn't practical.
One effective approach combines Ansible's with_fileglob
loop with conditional excludes:
- name: Copy all files except excluded patterns
ansible.builtin.copy:
src: "{{ item }}"
dest: /target/path/
with_fileglob:
- /source/path/*
- /source/path/.*
when: "item not in ['/source/path/excluded_file', '/source/path/excluded_dir']"
For more complex exclusion patterns, use the regex_filter
parameter with the find
module:
- name: Find all files except those matching pattern
ansible.builtin.find:
paths: /source/path
recurse: yes
patterns: "*"
excludes: "*.tmp,*.bak"
use_regex: yes
register: files_to_copy
- name: Copy filtered files
ansible.builtin.copy:
src: "{{ item.path }}"
dest: "/target/path/{{ item.path | regex_replace('^/source/path/', '') }}"
loop: "{{ files_to_copy.files }}"
For large directory operations, consider synchronize
module with rsync patterns:
- name: Sync directory with exclusions
ansible.builtin.synchronize:
src: /source/path/
dest: /target/path/
rsync_opts:
- "--exclude=temp/"
- "--exclude=*.log"
When dealing with hundreds of files:
- The
find
+copy
approach has better performance than multiple individual copy tasks - For cross-platform compatibility, test exclusion patterns on different OS environments
- Consider pre-processing file lists in variables for complex exclusion logic