AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,400 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of 8 Ansible books published by Apress and Leanpub including "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example", and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

Ansible Delete Files in Directory: find & file Modules (Examples)

By Luca Berton · Published 2024-01-01 · Category: troubleshooting

How to delete only files inside a directory in Ansible using find and file modules. Clean up logs, temp files, and old backups by age, pattern, and size.

Ansible Delete Files in Directory: find & file Modules (Examples)

How to Delete Only Files Inside a Directory with Ansible?

I'm going to show you a live Playbook with some simple Ansible code. I'm Luca Berton and welcome to today's episode of Ansible Pilot.

See also: Ansible Delete File: Remove Files & Directories with file Module

Ansible How to Delete Only Files Inside a Directory

ansible.builtin.find • Return a list of files based on specific criteria

Today we're talking about the Ansible module find. The full name is ansible.builtin.find, which means that is part of the collection included in the ansible-core builtin collection. This module returns a list of files based on specific criteria using the find popular Unix command.

Parameters

• paths string - List of paths of directories to search • hidden boolean - no/yes • recurse boolean - recursively descend into the directory looking for files • file_type string - file/directory/any/link

The most important parameters of the find module for this use case. The mandatory parameter paths specify the list of paths of directories to search. You could include hidden files with the hidden parameter. As well as recurse in any directory under the main path with the recurse parameter. Another useful parameter is file_type, defaults to file but you could filter for directory, link or any filesystem object type.

See also: Ansible Backup Windows 10/11/2019/2022: win_robocopy Playbook (Guide)

Links

ansible.builtin.findansible.builtin.file

## Playbook

How to delete Ooly files inside a directory with Ansible Playbook. I'm going to delete only the files and directories under the example folder of my login user (devops).

code

---
- name: delete file(s) in dir Playbook
  hosts: all
  vars:
    mypath: "/home/devops/example"
  tasks:
    - name: collect files
      ansible.builtin.find:
        paths: "{{ mypath }}"
        hidden: true
        recurse: true
        file_type: any
      register: collected_files
    - name: remove collected files
      ansible.builtin.file:
        path: "{{ item.path }}"
        state: absent
      with_items: "{{ collected_files }}"

execution

$ ansible-playbook -i virtualmachines/demo/inventory delete\ file\ or\ directory/file_onlyfiles.yml
PLAY [delete file(s) in dir Playbook] *****************************************************************
TASK [Gathering Facts] ****************************************************************************
ok: [demo.example.com]
TASK [collect files] ******************************************************************************
ok: [demo.example.com]
TASK [remove collected files and directories] *****************************************************
changed: [demo.example.com] => (item={'path': '/home/devops/example/file1.txt', 'mode': '0644', 'isdir': False, 'ischr': False, 'isblk': False, 'isreg': True, 'isfifo': False, 'islnk': False, 'issock': False, 'uid': 1001, 'gid': 10, 'size': 0, 'inode': 484310, 'dev': 64768, 'nlink': 1, 'atime': 1652197335.6893907, 'mtime': 1652197335.6893907, 'ctime': 1652197335.6893907, 'gr_name': 'wheel', 'pw_name': 'devops', 'wusr': True, 'rusr': True, 'xusr': False, 'wgrp': False, 'rgrp': True, 'xgrp': False, 'woth': False, 'roth': True, 'xoth': False, 'isuid': False, 'isgid': False})
changed: [demo.example.com] => (item={'path': '/home/devops/example/file2.txt', 'mode': '0644', 'isdir': False, 'ischr': False, 'isblk': False, 'isreg': True, 'isfifo': False, 'islnk': False, 'issock': False, 'uid': 1001, 'gid': 10, 'size': 0, 'inode': 484311, 'dev': 64768, 'nlink': 1, 'atime': 1652197337.6393802, 'mtime': 1652197337.6393802, 'ctime': 1652197337.6393802, 'gr_name': 'wheel', 'pw_name': 'devops', 'wusr': True, 'rusr': True, 'xusr': False, 'wgrp': False, 'rgrp': True, 'xgrp': False, 'woth': False, 'roth': True, 'xoth': False, 'isuid': False, 'isgid': False})
changed: [demo.example.com] => (item={'path': '/home/devops/example/deleteme', 'mode': '0755', 'isdir': True, 'ischr': False, 'isblk': False, 'isreg': False, 'isfifo': False, 'islnk': False, 'issock': False, 'uid': 1001, 'gid': 10, 'size': 23, 'inode': 201823954, 'dev': 64768, 'nlink': 2, 'atime': 1652197359.8632617, 'mtime': 1652197356.4072802, 'ctime': 1652197356.4072802, 'gr_name': 'wheel', 'pw_name': 'devops', 'wusr': True, 'rusr': True, 'xusr': True, 'wgrp': False, 'rgrp': True, 'xgrp': True, 'woth': False, 'roth': True, 'xoth': True, 'isuid': False, 'isgid': False})
ok: [demo.example.com] => (item={'path': '/home/devops/example/deleteme/file3.txt', 'mode': '0644', 'isdir': False, 'ischr': False, 'isblk': False, 'isreg': True, 'isfifo': False, 'islnk': False, 'issock': False, 'uid': 1001, 'gid': 10, 'size': 0, 'inode': 201823955, 'dev': 64768, 'nlink': 1, 'atime': 1652197356.4072802, 'mtime': 1652197356.4072802, 'ctime': 1652197356.4072802, 'gr_name': 'wheel', 'pw_name': 'devops', 'wusr': True, 'rusr': True, 'xusr': False, 'wgrp': False, 'rgrp': True, 'xgrp': False, 'woth': False, 'roth': True, 'xoth': False, 'isuid': False, 'isgid': False})
PLAY RECAP ****************************************************************************************
demo.example.com           : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
idempotency
$ ansible-playbook -i virtualmachines/demo/inventory delete\ file\ or\ directory/file_onlyfiles.yml
PLAY [delete file(s) in dir Playbook] *****************************************************************
TASK [Gathering Facts] ****************************************************************************
ok: [demo.example.com]
TASK [collect files] ******************************************************************************
ok: [demo.example.com]
TASK [remove collected files and directories] *****************************************************
PLAY RECAP ****************************************************************************************
demo.example.com           : ok=2    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

before execution

$ ssh devops@demo.example.com
[devops@demo ~]$ tree example/
example/
|-- deleteme
|   `-- file3.txt
|-- file1.txt
`-- file2.txt
1 directory, 3 files

after execution

$ ssh devops@demo.example.com
[devops@demo ~]$ tree example/
example/
0 directories, 0 files

code with ❤️ in GitHub

Conclusion

Now you know how to delete only files inside a directory with Ansible.

See also: Ansible Create Directory: file Module with state=directory (Guide)

Delete All Files in Directory

- name: Find all files
  ansible.builtin.find:
    paths: /tmp/myapp
    file_type: file
  register: files_to_delete

- name: Delete found files ansible.builtin.file: path: "{{ item.path }}" state: absent loop: "{{ files_to_delete.files }}" become: true

Delete by Pattern

- find:
    paths: /var/log/myapp
    patterns: "*.log.gz"
  register: compressed_logs

- file: { path: "{{ item.path }}", state: absent } loop: "{{ compressed_logs.files }}" become: true

Delete by Age

# Delete files older than 30 days
- find:
    paths: /var/log/myapp
    age: 30d
    file_type: file
  register: old_files

- file: { path: "{{ item.path }}", state: absent } loop: "{{ old_files.files }}" become: true

Delete by Size

# Delete files larger than 100MB
- find:
    paths: /var/log
    size: 100m
    file_type: file
    recurse: true
  register: large_files

- file: { path: "{{ item.path }}", state: absent } loop: "{{ large_files.files }}" become: true

Delete Files Recursively

- find:
    paths: /opt/myapp/cache
    recurse: true
    file_type: file
  register: cache_files

- file: { path: "{{ item.path }}", state: absent } loop: "{{ cache_files.files }}"

Keep Directory, Delete Contents

# Method 1: Find and delete
- find:
    paths: /tmp/build
    file_type: any  # Files AND directories
    hidden: true
  register: build_contents

- file: { path: "{{ item.path }}", state: absent } loop: "{{ build_contents.files }}"

# Method 2: Remove and recreate - file: { path: /tmp/build, state: absent } - file: { path: /tmp/build, state: directory, mode: '0755' }

Exclude Pattern

# Delete everything EXCEPT .conf files
- find:
    paths: /opt/myapp/config
    excludes: "*.conf"
    file_type: file
  register: non_config

- file: { path: "{{ item.path }}", state: absent } loop: "{{ non_config.files }}"

Combined Criteria

# Old log files larger than 10MB
- find:
    paths: /var/log
    patterns: "*.log*"
    age: 7d
    size: 10m
    recurse: true
  register: cleanup

- debug: msg: "Cleaning {{ cleanup.files | length }} files ({{ cleanup.files | map(attribute='size') | sum // 1048576 }}MB)"

- file: { path: "{{ item.path }}", state: absent } loop: "{{ cleanup.files }}" become: true

find Module Parameters

| Parameter | Description | |-----------|-------------| | paths | Directories to search | | patterns | Filename patterns (glob) | | excludes | Patterns to exclude | | age | Min age (e.g., 7d, 4w, 2m) | | age_stamp | mtime, atime, or ctime | | size | Min size (e.g., 10m, 1g) | | file_type | file, directory, link, any | | recurse | Search subdirectories | | hidden | Include hidden files | | contains | Regex to match file content |

FAQ

Why not just use shell: rm?

find + file is idempotent, handles errors gracefully, and reports exactly what changed. shell: rm is a black box to Ansible.

Can I delete empty directories?

- find:
    paths: /opt/myapp
    file_type: directory
    recurse: true
  register: dirs
# Then check each is empty before deleting

How do I do a dry run?

Just run the find task and print results without the file: absent task.

Related Articles

Ansible inventory best practicesusing the ansible.builtin.file module

Category: troubleshooting

Watch the video: Ansible Delete Files in Directory: find & file Modules (Examples) — Video Tutorial

Browse all Ansible tutorials · AnsiblePilot Home