Ansible Move File: Relocate Files Between Directories (Complete Guide)
By Luca Berton · Published 2024-01-01 · Category: installation
How to move files in Ansible between directories. Use copy+file modules, command module with mv, synchronize module.
Ansible Move File: Relocate Files Between Directories (Complete Guide)
Moving files between directories is a common task in system administration, but Ansible doesn't have a dedicated "move" module. This guide covers all practical approaches to move files with Ansible, from the recommended copy+delete pattern to using the command module.
See also: Ansible Create File with Content: Write Text to Files (Complete Guide)
Why No ansible.builtin.move Module?
Ansible follows an idempotent design philosophy. A "move" operation is inherently non-idempotent — running it twice would fail because the source no longer exists after the first run. Instead, Ansible provides building blocks that you combine for safe, repeatable file operations.
Method 1: Copy + Delete Pattern (Recommended)
The safest and most idempotent approach uses ansible.builtin.copy to copy the file, then ansible.builtin.file to remove the original:
---
- name: Move file using copy + delete pattern
hosts: all
tasks:
- name: Copy file to new location
ansible.builtin.copy:
src: /opt/app/config.yml
dest: /etc/app/config.yml
remote_src: true
owner: root
group: root
mode: '0644'
- name: Remove original file
ansible.builtin.file:
path: /opt/app/config.yml
state: absent
Key parameter: remote_src: true tells Ansible to copy between paths on the remote host (not from the control node).
See also: Ansible Move File: Rename & Move Files on Remote Hosts (Complete Guide)
Method 2: Command Module with mv
For simple moves where idempotency is handled by conditionals:
---
- name: Move file with command module
hosts: all
tasks:
- name: Check if source file exists
ansible.builtin.stat:
path: /tmp/upload/data.csv
register: source_file
- name: Move file to target directory
ansible.builtin.command:
cmd: mv /tmp/upload/data.csv /var/lib/app/data.csv
when: source_file.stat.exists
Move with creates/removes Guards
Use creates and removes parameters for built-in idempotency:
- name: Move file with idempotency guards
ansible.builtin.command:
cmd: mv /tmp/installer.bin /opt/installers/installer.bin
removes: /tmp/installer.bin
creates: /opt/installers/installer.bin
Method 3: Rename a File
Renaming is just moving to the same directory with a different name:
- name: Rename configuration file
ansible.builtin.command:
cmd: mv /etc/app/config.yml.bak /etc/app/config.yml
removes: /etc/app/config.yml.bak
creates: /etc/app/config.yml
See also: Ansible Create File with Content: copy Module content Parameter
Method 4: Move Multiple Files with find + loop
Move all files matching a pattern:
---
- name: Move all log files to archive
hosts: all
tasks:
- name: Find all .log files in /var/log/app
ansible.builtin.find:
paths: /var/log/app
patterns: "*.log"
age: "7d"
register: old_logs
- name: Copy log files to archive
ansible.builtin.copy:
src: "{{ item.path }}"
dest: "/var/log/archive/{{ item.path | basename }}"
remote_src: true
loop: "{{ old_logs.files }}"
- name: Remove original log files
ansible.builtin.file:
path: "{{ item.path }}"
state: absent
loop: "{{ old_logs.files }}"
Method 5: Move Directories
Move an entire directory tree:
---
- name: Move directory to new location
hosts: all
tasks:
- name: Synchronize directory to new location
ansible.posix.synchronize:
src: /opt/old-app/
dest: /opt/new-app/
delete: false
delegate_to: "{{ inventory_hostname }}"
- name: Remove original directory
ansible.builtin.file:
path: /opt/old-app
state: absent
Or with the command module:
- name: Move directory with mv
ansible.builtin.command:
cmd: mv /opt/old-app /opt/new-app
removes: /opt/old-app
creates: /opt/new-app
Method 6: Move Files Between Remote Hosts
Use ansible.builtin.fetch + ansible.builtin.copy:
---
- name: Fetch file from source host
hosts: source_server
tasks:
- name: Download file to control node
ansible.builtin.fetch:
src: /var/data/export.sql
dest: /tmp/transfer/
flat: true
- name: Deploy file to destination host
hosts: dest_server
tasks:
- name: Upload file to destination
ansible.builtin.copy:
src: /tmp/transfer/export.sql
dest: /var/data/import.sql
owner: postgres
group: postgres
mode: '0600'
Comparison: Which Method to Use
| Method | Best For | Idempotent | Preserves Permissions | |--------|----------|------------|----------------------| | copy + delete | Single files, safety | ✅ Yes | ✅ Yes (set explicitly) | | command mv | Speed, large files | ⚠️ With guards | ✅ Yes | | synchronize | Directories | ✅ Yes | ✅ Yes | | fetch + copy | Cross-host | ✅ Yes | ✅ Yes | | find + loop | Pattern matching | ✅ Yes | ✅ Yes |
Common Mistakes
1. Forgetting remote_src
# WRONG — tries to copy from control node
- ansible.builtin.copy:
src: /etc/app/old.conf
dest: /etc/app/new.conf
# CORRECT — copies on the remote host
- ansible.builtin.copy:
src: /etc/app/old.conf
dest: /etc/app/new.conf
remote_src: true
2. Not Checking Source Exists
# WRONG — fails if source doesn't exist
- ansible.builtin.command:
cmd: mv /tmp/file.txt /opt/file.txt
# CORRECT — skips if source is gone
- ansible.builtin.command:
cmd: mv /tmp/file.txt /opt/file.txt
removes: /tmp/file.txt
3. Missing Target Directory
# Ensure target directory exists first
- ansible.builtin.file:
path: /opt/target-dir
state: directory
mode: '0755'
- ansible.builtin.command:
cmd: mv /tmp/file.txt /opt/target-dir/file.txt
removes: /tmp/file.txt
FAQ
How do I move a file in Ansible?
Use the copy module with remote_src: true to copy the file to the new location, then the file module with state: absent to remove the original. Alternatively, use ansible.builtin.command with mv and removes/creates guards for idempotency.
Why doesn't Ansible have a move module?
Ansible is designed for idempotent operations. A move operation is inherently non-idempotent because the source file no longer exists after the first run. The copy + delete pattern achieves the same result while being safely repeatable.
Can I move files between two remote hosts with Ansible?
Yes. Use ansible.builtin.fetch to download the file from the source host to the control node, then ansible.builtin.copy to upload it to the destination host. For directory synchronization, use ansible.posix.synchronize.
How do I rename a file in Ansible?
Renaming is moving a file within the same directory. Use ansible.builtin.command with mv /path/old-name /path/new-name and removes/creates guards, or the copy + delete pattern with remote_src: true.
How do I move multiple files matching a pattern?
Use ansible.builtin.find to locate files matching your pattern, register the results, then loop over them with copy + file delete. See the "Move Multiple Files" example above.
Conclusion
While Ansible lacks a dedicated move module, the copy + delete pattern provides a safe, idempotent approach for most scenarios. Use ansible.builtin.command with mv for performance-critical operations on large files, and ansible.posix.synchronize for directory moves.
Related Articles
• Ansible Create Directory: file Module state=directory Guide • Ansible Delete File: Remove Files & Directories • Ansible Rename File: Move & Rename Files • ansible.builtin.find Module: Search Files by Pattern • Ansible Fetch Module: Copy Files from Remote HostsCategory: installation