When using Ansible's synchronize module, you'll encounter this common scenario: you want to copy the contents of a directory to a target location without preserving the parent directory structure. By default, running:
- name: Basic directory sync
synchronize:
src: files/to/synchronize
dest: /tmp/1
Creates /tmp/1/synchronize/ containing your files, when what you really want is all files directly in /tmp/1/.
The key is leveraging rsync's --relative and --no-implied-dirs flags through Ansible's rsync_opts parameter:
- name: Sync directory contents only
synchronize:
src: files/to/synchronize/
dest: /tmp/1/
rsync_opts:
- "--relative"
- "--no-implied-dirs"
archive: yes
Important notes about this solution:
- The trailing slashes on both
srcanddestare crucial archive: yespreserves permissions and timestamps- Works with recursive directory structures
For smaller directory trees, you might consider Ansible's copy module with content: yes:
- name: Copy directory contents
copy:
src: "files/to/synchronize/"
dest: "/tmp/1/"
remote_src: yes
content: yes
Limitations to be aware of:
- Doesn't support delta transfers like rsync
- Less efficient for large directories
- No native checksum verification
For complex scenarios where you need to exclude certain patterns:
- name: Sync with exclusions
synchronize:
src: "files/to/synchronize/"
dest: "/tmp/1/"
rsync_opts:
- "--relative"
- "--no-implied-dirs"
- "--exclude=*.tmp"
- "--exclude=.git/"
checksum: yes
delete: yes
This configuration will:
- Skip temporary files and Git directories
- Use checksums for change detection
- Remove files in destination not present in source
When using Ansible's synchronize module, you'll notice it preserves the entire source directory structure by default. For example, syncing files/to/synchronize to /tmp/1 creates /tmp/1/synchronize - an extra directory level you may not want.
The key is to leverage rsync's --relative and --no-implied-dirs flags through Ansible's rsync_flags parameter:
- name: Sync directory contents without parent folder
synchronize:
src: files/to/synchronize/
dest: /tmp/1/
rsync_flags:
- "--relative"
- "--no-implied-dirs"
- "--copy-links"
recursive: yes
delete: yes
1. Trailing slashes matter: Both src and dest should end with /
2. --relative preserves path relativity without the parent dir
3. --no-implied-dirs prevents automatic directory creation
4. Add delete: yes for true mirror synchronization
For smaller directory trees, you might prefer the copy module with remote_src:
- name: Copy directory contents
copy:
src: "files/to/synchronize/"
dest: "/tmp/1/"
remote_src: no
The synchronize method is significantly faster for large directories as it uses rsync's delta-transfer algorithm. Benchmark tests show 3-5x speed improvement over copy for directories exceeding 1GB.
If you encounter permission problems, add these rsync flags:
rsync_flags:
- "--chmod=Du=rwx,Dg=rx,Do=rx,Fu=rw,Fg=r,Fo=r"
- "--times"
- "--omit-dir-times"