Ansible find Module — Search for Files and Directories

What Is the Ansible find Module?

The ansible.builtin.find module searches for files matching specific criteria — name patterns, age, size, content, and type. It's the Ansible equivalent of the Linux find command, returning a list of matching files that you can feed into subsequent tasks for cleanup, backup, or processing.

Parameters Reference

ParameterTypeDefaultDescription
pathslistrequiredDirectories to search
patternslist'*'Filename patterns (shell glob or regex)
use_regexbooleanfalseTreat patterns as Python regex
agestring—File age filter (7d, 4w, -1h)
age_stampstringmtimeTimestamp: atime, ctime, mtime
sizestring—Size filter (1m, -500k, 10g)
file_typestringfileType: file, directory, link, any
recursebooleanfalseSearch subdirectories
hiddenbooleanfalseInclude hidden files
containsstring—Regex to match file content
excludeslist—Patterns to exclude
depthinteger—Maximum recursion depth

Find and Delete Old Logs

---
- name: Clean up old log files
  hosts: all
  become: true
  tasks:
    - name: Find logs older than 30 days
      ansible.builtin.find:
        paths: /var/log
        patterns: '*.log,*.log.gz'
        age: 30d
        recurse: true
      register: old_logs

    - name: Show what will be deleted
      ansible.builtin.debug:
        msg: "Found {{ old_logs.matched }} files ({{ old_logs.examined }} examined)"

    - name: Delete old logs
      ansible.builtin.file:
        path: "{{ item.path }}"
        state: absent
      loop: "{{ old_logs.files }}"
      loop_control:
        label: "{{ item.path }}"

Find Large Files

    - name: Find files larger than 100MB
      ansible.builtin.find:
        paths: /home
        size: 100m
        recurse: true
      register: large_files

    - name: Report large files
      ansible.builtin.debug:
        msg: "{{ item.path }} — {{ (item.size / 1048576) | round(1) }}MB"
      loop: "{{ large_files.files }}"
      when: large_files.matched > 0

Find Files by Content

    - name: Find configs with hardcoded passwords
      ansible.builtin.find:
        paths: /etc
        patterns: '*.conf,*.ini,*.yml'
        contains: 'password\s*[=:]\s*[^$]'
        recurse: true
      register: password_files

    - name: Alert on found files
      ansible.builtin.debug:
        msg: "WARNING: {{ item.path }} may contain hardcoded passwords"
      loop: "{{ password_files.files }}"

Find Empty Directories

    - name: Find empty directories
      ansible.builtin.find:
        paths: /opt/app/data
        file_type: directory
        recurse: true
      register: all_dirs

    - name: Remove empty directories
      ansible.builtin.file:
        path: "{{ item.path }}"
        state: absent
      loop: "{{ all_dirs.files }}"
      when: item.isdir and (item.path | basename) != 'data'

Find Recently Modified Files

    - name: Find files modified in last hour
      ansible.builtin.find:
        paths: /etc
        age: -1h
        recurse: true
      register: recent_changes

    - name: Report recent changes (possible drift)
      ansible.builtin.debug:
        msg: "Changed: {{ item.path }} at {{ item.mtime }}"
      loop: "{{ recent_changes.files }}"

Using Regex Patterns

    - name: Find files matching regex
      ansible.builtin.find:
        paths: /var/backups
        patterns: '^backup-\d{4}-\d{2}-\d{2}\.tar\.gz$'
        use_regex: true

Return Values

The module returns a list of file objects with these properties:

PropertyDescription
pathFull file path
sizeSize in bytes
mtimeModification time (epoch)
modeFile permissions
uidOwner UID
gidGroup GID
isdirIs directory
islnkIs symlink
matchedTotal files matched
examinedTotal files examined

Troubleshooting

  • No files found — Check recurse: true for subdirectories
  • Age filter direction — Positive age (30d) = older than; negative (-1h) = newer than
  • Size units — k=kilobytes, m=megabytes, g=gigabytes
  • Permission denied — Use become: true for system directories
  • Too many results — Add depth parameter to limit recursion

Conclusion

The ansible.builtin.find module replaces ad-hoc find commands with structured, idempotent file discovery. Combine it with ansible.builtin.file for cleanup, ansible.builtin.fetch for collection, or ansible.builtin.debug for auditing. The age, size, and content filters make it perfect for log rotation, disk cleanup, and security audits.