ansible.builtin.find Module: Search Files by Pattern, Size & Age (Guide)
By Luca Berton · Published 2024-01-01 · Category: troubleshooting
How to find files with Ansible find module (ansible.builtin.find). Search by extension, name pattern, size, age, type.

How to Find All Files with a specific Extension 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 Search String in File: lineinfile & regex Guide
Ansible Find All Files with Extension
•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 • patterns list - search (shell or regex) pattern(s) • use_regex boolean - no/yes - file globs (shell) / python regexesThe 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, which defaults to file but you could filter for directory, link, or any filesystem object type.
Specify what to search under the patterns list.
Ansible by default uses file globs (shell) patterns but you could specify also python regexes enabling the use_regex parameter.
See also: Ansible Delete File: Remove Files & Directories (state=absent Guide)
Links
•ansible.builtin.find
Playbook
How to Find All Files with Extension with Ansible Playbook. I'm going to search only the files and directories under the example folder of my login users (devops) and list all the files with the ".cnf" extension. This code has no dangerous effect on the target machine.code
---
- name: find Playbook
hosts: all
vars:
mypath: "/home/devops/example"
mypattern: '*.cnf'
tasks:
- name: search files
ansible.builtin.find:
paths: "{{ mypath }}"
hidden: true
recurse: true
file_type: any
patterns: "{{ mypattern }}"
register: found_files
- name: print files
ansible.builtin.debug:
var: found_files
execution
$ ansible-playbook -i virtualmachines/demo/inventory file_management/file_find.yml
PLAY [find Playbook] **********************************************************************************
TASK [Gathering Facts] ****************************************************************************
ok: [demo.example.com]
TASK [search files] *******************************************************************************
ok: [demo.example.com]
TASK [print files] ********************************************************************************
ok: [demo.example.com] => {
"found_files": {
"changed": false,
"examined": 3,
"failed": false,
"files": [
{
"atime": 1657183703.9653573,
"ctime": 1657183703.9653573,
"dev": 64768,
"gid": 10,
"gr_name": "wheel",
"inode": 134965918,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"mode": "0644",
"mtime": 1657183703.9653573,
"nlink": 1,
"path": "/home/devops/example/file1.cnf",
"pw_name": "devops",
"rgrp": true,
"roth": true,
"rusr": true,
"size": 0,
"uid": 1001,
"wgrp": false,
"woth": false,
"wusr": true,
"xgrp": false,
"xoth": false,
"xusr": false
},
{
"atime": 1657183705.7742639,
"ctime": 1657183705.7742639,
"dev": 64768,
"gid": 10,
"gr_name": "wheel",
"inode": 134965931,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"mode": "0644",
"mtime": 1657183705.7742639,
"nlink": 1,
"path": "/home/devops/example/file2.cnf",
"pw_name": "devops",
"rgrp": true,
"roth": true,
"rusr": true,
"size": 0,
"uid": 1001,
"wgrp": false,
"woth": false,
"wusr": true,
"xgrp": false,
"xoth": false,
"xusr": false
}
],
"matched": 2,
"msg": "All paths examined",
"skipped_paths": {}
}
}
PLAY RECAP ****************************************************************************************
demo.example.com : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
idempotency
$ ansible-playbook -i virtualmachines/demo/inventory file_management/file_find.yml
PLAY [find Playbook] **********************************************************************************
TASK [Gathering Facts] ****************************************************************************
ok: [demo.example.com]
TASK [search files] *******************************************************************************
ok: [demo.example.com]
TASK [print files] ********************************************************************************
ok: [demo.example.com] => {
"found_files": {
"changed": false,
"examined": 3,
"failed": false,
"files": [
{
"atime": 1657183703.9653573,
"ctime": 1657183703.9653573,
"dev": 64768,
"gid": 10,
"gr_name": "wheel",
"inode": 134965918,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"mode": "0644",
"mtime": 1657183703.9653573,
"nlink": 1,
"path": "/home/devops/example/file1.cnf",
"pw_name": "devops",
"rgrp": true,
"roth": true,
"rusr": true,
"size": 0,
"uid": 1001,
"wgrp": false,
"woth": false,
"wusr": true,
"xgrp": false,
"xoth": false,
"xusr": false
},
{
"atime": 1657183705.7742639,
"ctime": 1657183705.7742639,
"dev": 64768,
"gid": 10,
"gr_name": "wheel",
"inode": 134965931,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"mode": "0644",
"mtime": 1657183705.7742639,
"nlink": 1,
"path": "/home/devops/example/file2.cnf",
"pw_name": "devops",
"rgrp": true,
"roth": true,
"rusr": true,
"size": 0,
"uid": 1001,
"wgrp": false,
"woth": false,
"wusr": true,
"xgrp": false,
"xoth": false,
"xusr": false
}
],
"matched": 2,
"msg": "All paths examined",
"skipped_paths": {}
}
}
PLAY RECAP ****************************************************************************************
demo.example.com : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
before execution
$ ssh devops@demo.example.com
[devops@demo ~]$ cd example
[devops@demo example]$ ls
file1.cnf file2.cnf file3.txt
[devops@demo example]$ tree
.
|-- file1.cnf
|-- file2.cnf
`-- file3.txt
0 directories, 3 files
[devops@demo example]$
after execution
$ ssh devops@demo.example.com
[devops@demo ~]$ cd example
[devops@demo example]$ ls
file1.cnf file2.cnf file3.txt
[devops@demo example]$ tree
.
|-- file1.cnf
|-- file2.cnf
`-- file3.txt
0 directories, 3 files
[devops@demo example]$
See also: Ansible Check If Directory Exists: stat Module Guide
Conclusion
Now you know how to Find All Files with Extension with Ansible.Find by Extension
- ansible.builtin.find:
paths: /var/log
patterns: '*.log'
register: log_files
- debug:
msg: "Found {{ log_files.files | length }} log files"
Find by Multiple Extensions
- find:
paths: /opt/myapp
patterns:
- '*.log'
- '*.tmp'
- '*.bak'
register: cleanup_files
Find by Age
# Files older than 30 days
- find:
paths: /var/log
patterns: '*.log'
age: 30d
register: old_logs
# Files newer than 1 hour
- find:
paths: /tmp
age: -1h
register: recent_files
Find by Size
# Files larger than 100MB
- find:
paths: /var/log
size: 100m
register: large_files
# Files smaller than 1KB
- find:
paths: /opt/configs
size: -1k
register: small_files
Find and Delete
# Find old temp files and remove them
- find:
paths: /tmp
patterns: '*.tmp'
age: 7d
register: old_temp
- file:
path: "{{ item.path }}"
state: absent
loop: "{{ old_temp.files }}"
become: true
Recursive Search
- find:
paths: /opt/myapp
patterns: '*.conf'
recurse: true
register: all_configs
Find Directories
- find:
paths: /opt
file_type: directory
patterns: 'cache*'
register: cache_dirs
Find with Regex
- find:
paths: /var/log
patterns: 'access\.log\.\d+'
use_regex: true
register: rotated_logs
Find by Content (contains)
- find:
paths: /etc/nginx/conf.d
patterns: '*.conf'
contains: 'server_name.*example\.com'
register: example_configs
Find Empty Files
- find:
paths: /var/log
size: 0
recurse: true
register: empty_files
Practical: Log Rotation Cleanup
- name: Find compressed logs older than 90 days
find:
paths: /var/log
patterns: '*.gz'
age: 90d
recurse: true
register: old_compressed
- name: Calculate space to reclaim
set_fact:
space_mb: "{{ old_compressed.files | map(attribute='size') | sum / 1048576 }}"
- debug:
msg: "Removing {{ old_compressed.files | length }} files ({{ space_mb | round(1) }} MB)"
- name: Remove old compressed logs
file:
path: "{{ item.path }}"
state: absent
loop: "{{ old_compressed.files }}"
become: true
Practical: Find and Archive
- find:
paths: /opt/myapp/reports
patterns: '*.csv'
age: 30d
register: old_reports
- archive:
path: "{{ old_reports.files | map(attribute='path') | list }}"
dest: /opt/backups/old-reports.tar.gz
when: old_reports.files | length > 0
Key Parameters
| Parameter | Description |
|-----------|-------------|
| paths | Directories to search |
| patterns | Filename patterns (glob or regex) |
| use_regex | Enable regex patterns |
| recurse | Search subdirectories |
| age | Filter by age (e.g., 30d, 1h, 2w) |
| size | Filter by size (e.g., 100m, 1g) |
| file_type | file, directory, link, any |
| contains | Filter by file content regex |
| hidden | Include hidden files |
| excludes | Patterns to exclude |
FAQ
How do I use the results in a loop?
Access result.files — each item has .path, .size, .mtime, .mode:
loop: "{{ found.files }}"
msg: "{{ item.path }} ({{ item.size }} bytes)"
find vs shell find command?
The find module returns structured data (JSON), is idempotent, and cross-platform. shell: find is faster for complex queries but returns raw text.
Can I search multiple directories?
Yes: paths: [/var/log, /opt/logs, /tmp]
Find by Extension
- ansible.builtin.find:
paths: /var/log
patterns: "*.log"
register: log_files
- debug:
msg: "Found {{ log_files.files | length }} log files"
Find by Age
# Files older than 30 days
- find:
paths: /var/log
age: 30d
recurse: true
register: old_files
# Files newer than 1 hour
- find:
paths: /opt/uploads
age: -1h
register: new_files
Find by Size
# Files larger than 100MB
- find:
paths: /var/log
size: 100m
recurse: true
register: large_files
Find and Delete
- find:
paths: /tmp
patterns: "*.tmp"
age: 7d
register: old_tmp
- file:
path: "{{ item.path }}"
state: absent
loop: "{{ old_tmp.files }}"
become: true
Multiple Patterns
- find:
paths: /opt/backups
patterns:
- "*.tar.gz"
- "*.zip"
- "*.bak"
recurse: true
register: backup_files
Find Directories
- find:
paths: /opt
file_type: directory
patterns: "cache*"
register: cache_dirs
Find by Content
- find:
paths: /etc
patterns: "*.conf"
contains: "password"
recurse: true
register: files_with_passwords
Exclude Patterns
- find:
paths: /var/log
patterns: "*.log"
excludes:
- "*.log.gz"
- "syslog*"
register: active_logs
Process Found Files
- find:
paths: /opt/myapp/data
patterns: "*.csv"
register: csv_files
- command: "python3 /opt/process.py {{ item.path }}"
loop: "{{ csv_files.files }}"
Cleanup Playbook
- hosts: all
become: true
tasks:
- find:
paths:
- /var/log
- /tmp
patterns: ["*.gz", "*.old", "*.bak"]
age: 30d
recurse: true
register: cleanup_targets
- file:
path: "{{ item.path }}"
state: absent
loop: "{{ cleanup_targets.files }}"
- debug:
msg: "Cleaned {{ cleanup_targets.files | length }} files, freed {{ cleanup_targets.files | map(attribute='size') | sum | human_readable }}"
FAQ
find vs shell find command?
Ansible find is idempotent, cross-platform, and returns structured data. Use it instead of shell: find ....
How to limit results?
No built-in limit, but filter in Jinja2: {{ files.files | sort(attribute='mtime') | last }} for newest.
Can I find files across multiple directories?
Yes — paths accepts a list of directories to search.
Related Articles
• Ansible inventory complete referenceCategory: troubleshooting
Watch the video: ansible.builtin.find Module: Search Files by Pattern, Size & Age (Guide) — Video Tutorial