Ansible Delete File & Remove File: file Module absent State Guide
By Luca Berton · Published 2024-01-01 · Category: database-automation
How to delete and remove files in Ansible with the file module (state=absent). Delete files, remove directories recursively, manage symlinks and permissions.
Ansible provides several modules for file operations: file (create/delete/permissions/links), copy (create files with content), stat (check existence), and command/shell for moves and renames. This guide covers every common file operation.
Create Files and Directories
Create an Empty File
- name: Create empty file
ansible.builtin.file:
path: /opt/app/config.yml
state: touch
owner: appuser
group: appuser
mode: '0644'
Create a File with Content
# Using copy module
- name: Create file with content
ansible.builtin.copy:
content: |
# Application Configuration
database_host: db.example.com
database_port: 5432
log_level: info
dest: /opt/app/config.yml
owner: appuser
mode: '0644'
# From a variable
- name: Write variable to file
ansible.builtin.copy:
content: "{{ my_config | to_nice_yaml }}"
dest: /opt/app/config.yml
mode: '0644'
Create Directory
- name: Create directory
ansible.builtin.file:
path: /opt/app/logs
state: directory
owner: appuser
group: appuser
mode: '0755'
# Create nested directories
- name: Create directory tree
ansible.builtin.file:
path: /opt/app/data/cache/sessions
state: directory
# Creates all parent directories automatically
Create Multiple Directories
- name: Create application directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: appuser
group: appuser
mode: '0755'
loop:
- /opt/app/config
- /opt/app/data
- /opt/app/logs
- /opt/app/tmp
See also: Ansible get_url Module Complete Reference: Checksums, Auth, Proxies & Retries
Delete Files and Directories
Delete a File
- name: Delete file
ansible.builtin.file:
path: /tmp/old-config.yml
state: absent
Delete a Directory (Recursively)
- name: Delete directory and all contents
ansible.builtin.file:
path: /opt/old-app
state: absent
Delete All Files in a Directory
# Find and delete files, keep directory
- name: Find all files in directory
ansible.builtin.find:
paths: /opt/app/logs
file_type: file
register: log_files
- name: Delete all log files
ansible.builtin.file:
path: "{{ item.path }}"
state: absent
loop: "{{ log_files.files }}"
# Or with patterns
- name: Delete old log files
ansible.builtin.find:
paths: /opt/app/logs
patterns: "*.log"
age: 30d
register: old_logs
- name: Remove old logs
ansible.builtin.file:
path: "{{ item.path }}"
state: absent
loop: "{{ old_logs.files }}"
Rename and Move Files
# Rename/move a file
- name: Rename file
ansible.builtin.command: mv /opt/app/config.yml.bak /opt/app/config.yml
args:
removes: /opt/app/config.yml.bak
creates: /opt/app/config.yml
# Rename a directory
- name: Rename directory
ansible.builtin.command: mv /opt/myapp-old /opt/myapp-new
args:
removes: /opt/myapp-old
creates: /opt/myapp-new
# Copy + delete (for cross-filesystem moves)
- name: Copy file to new location
ansible.builtin.copy:
src: /opt/app/config.yml
dest: /mnt/backup/config.yml
remote_src: true
- name: Remove original
ansible.builtin.file:
path: /opt/app/config.yml
state: absent
See also: Ansible 2.17.0-rc1: Elevating Automation with ‘Gallows Pole’
Symbolic Links
Create Symlink
- name: Create symbolic link
ansible.builtin.file:
src: /opt/app/releases/2.1.0
dest: /opt/app/current
state: link
# Symlink for binary
- name: Link binary to PATH
ansible.builtin.file:
src: /opt/app/current/bin/myapp
dest: /usr/local/bin/myapp
state: link
become: true
Update Symlink (Atomic Deploy)
- name: Deploy new version
ansible.builtin.unarchive:
src: "myapp-{{ version }}.tar.gz"
dest: /opt/app/releases/{{ version }}/
# Symlink update is atomic — no downtime
- name: Switch to new version
ansible.builtin.file:
src: /opt/app/releases/{{ version }}
dest: /opt/app/current
state: link
force: true # Overwrite existing symlink
notify: restart app
Remove Symlink
- name: Remove symbolic link
ansible.builtin.file:
path: /usr/local/bin/myapp
state: absent
Permissions and Ownership
Change Permissions (chmod)
- name: Set file permissions
ansible.builtin.file:
path: /opt/app/bin/start.sh
mode: '0755'
# Symbolic mode
- name: Add execute permission
ansible.builtin.file:
path: /opt/app/bin/start.sh
mode: 'u+x'
# Recursive permissions
- name: Set directory permissions recursively
ansible.builtin.file:
path: /opt/app/data
state: directory
recurse: true
mode: '0755'
Change Ownership (chown)
- name: Change file ownership
ansible.builtin.file:
path: /opt/app
owner: appuser
group: appgroup
recurse: true
become: true
Common Permission Patterns
# Private key
- name: Secure SSH key
ansible.builtin.file:
path: /home/deploy/.ssh/id_ed25519
owner: deploy
group: deploy
mode: '0600'
# Config file (owner read/write, group read)
- name: Set config permissions
ansible.builtin.file:
path: /etc/app/config.yml
owner: root
group: appuser
mode: '0640'
# Executable script
- name: Set script permissions
ansible.builtin.file:
path: /opt/app/bin/start.sh
mode: '0755'
# Shared directory
- name: Set shared directory
ansible.builtin.file:
path: /opt/shared
state: directory
mode: '2775' # setgid bit
group: sharedgroup
See also: Automating Jenkins Installation with Ansible
Check if File/Directory Exists
- name: Check if file exists
ansible.builtin.stat:
path: /opt/app/config.yml
register: config_file
- name: Create config if missing
ansible.builtin.template:
src: config.yml.j2
dest: /opt/app/config.yml
when: not config_file.stat.exists
# Check directory
- name: Check if directory exists
ansible.builtin.stat:
path: /opt/app/data
register: data_dir
- name: Initialize data directory
ansible.builtin.command: /opt/app/bin/init-data
when: not data_dir.stat.exists
Copy Multiple Files
# Using with_fileglob
- name: Copy all config files
ansible.builtin.copy:
src: "{{ item }}"
dest: /etc/app/conf.d/
owner: appuser
mode: '0644'
with_fileglob:
- "files/configs/*.conf"
# Using loop
- name: Copy specific files
ansible.builtin.copy:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
mode: "{{ item.mode | default('0644') }}"
loop:
- { src: app.conf, dest: /etc/app/app.conf }
- { src: logging.conf, dest: /etc/app/logging.conf }
- { src: start.sh, dest: /opt/app/bin/start.sh, mode: '0755' }
FAQ
How do I create a file with content in Ansible?
Use the copy module with content parameter: ansible.builtin.copy: content="my content" dest=/path/to/file. For templates with variables, use ansible.builtin.template instead.
How do I delete a file in Ansible?
Use the file module with state: absent: ansible.builtin.file: path=/path/to/file state=absent. This works for both files and directories (recursive delete).
How do I rename a file in Ansible?
Use ansible.builtin.command: mv /old/path /new/path with removes and creates arguments for idempotency. There's no dedicated rename module — the command module with mv is the standard approach.
How do I create a symbolic link?
Use the file module with state: link: ansible.builtin.file: src=/target dest=/link state=link. Use force: true to overwrite existing symlinks.
How do I change file permissions recursively?
Use the file module with recurse: true: ansible.builtin.file: path=/opt/app state=directory recurse=true mode='0755' owner=appuser.
How do I check if a file exists in Ansible?
Use the stat module and check register_var.stat.exists: register the result, then use when: not result.stat.exists or when: result.stat.exists in subsequent tasks.
Conclusion
| Operation | Module | Key Parameter |
|-----------|--------|---------------|
| Create empty file | file | state: touch |
| Create with content | copy | content: |
| Create directory | file | state: directory |
| Delete file/dir | file | state: absent |
| Rename/move | command | mv with creates/removes |
| Symlink | file | state: link |
| Permissions | file | mode: |
| Ownership | file | owner:, group: |
| Check exists | stat | .stat.exists |
Related Articles
• Ansible copy Module • Ansible template Module • Ansible unarchive Module: Extract Archives • Ansible Playbook Structure & Best PracticesCategory: database-automation