Ansible find module functions as same as the Linux Find command and helps to find files and directories based on various search criteria such as age of the file, accessed date, modified date, regex search pattern etcetera.
As said earlier, this is more of an ansible way to execute the Linux find command with some standard in place.
this module is intended to use only on Linux servers, For windows, you should use a win_find
module instead.
Since this is going to be a Linux Find command replacement alike. I would list out all the examples with the linux find equivalent.
Index:
- Example1: Find all the log files older than 30 days
- Example2: Find all the log files lesser than 30 days age
- Example3: Recursively find the files by Size using Ansible Find
- Example4: Find All directories excluding few, as a list
- Example5: Find Files with a Regex Pattern - Single or Multiple
- Example6: Ansible Find to Delete the matching files
Example1: Find all the log files older than 30 days with Ansible Find
In this section, we are going to see how ansible find is going to help us find the more than 30 days old files.
The Linux find Command
Here is the command that you would ideally execute in the Linux OS
find /var/log -name "*.log" -type f -mtime +30
The Ansible Find AdHoc Command
The same Linux command can be rewritten as ansible ad hoc command as follows
ansible appgroup -i ansible_hosts -m find -a "paths='/var/log' file_type=file patterns='*.log' age_stamp=mtime age=30d"
Look at the following Comparision table between Linux Find and Ansible Find attributes.
I think this would give you a clear picture.
With Linux Find | With Ansible Find |
-type f | file_type=file |
find /var/log | paths='/var/log' |
-name "*.log" | pattern="*.log" |
-mtime | age_stamp="mtime" |
+30 | age=30d |
A Playbook with Ansible Find
The same can be put into the playbook as shown below.
---
- name: Ansible Find Example
hosts: testserver
tasks:
- name : Find files older than 30 days
find:
paths: /var/log
patterns: '*.log'
age: 30d
age_stamp: mtime
register: output
- debug: var=item.path
with_items: "{{ output.files }}"
The playbook has two tasks, The First one is with the find module to find the files older than 30 days and the output of this task would be saved into a register variable named output
and then it would be used in the next play/task with Debug.
You could see that we are mentioning the age as 30d
to represent 30 days older files and specifying what time validation method should be used like mtime, atime, ctime with help of age_stamp: mtime
How to use keywords like ctime, mtime, atime with ansible find ?
By default,
age_stamp
parameter would be set tomtime
Based on your requirement it can be changed to
atime
orctime
it would function the similar way as same as Linux
How to use Seconds, Months, Weeks, Year as matric in the age ?
Ansible find supports you to use various matrics in age . By default it would be
seconds
You can choose seconds, minutes, hours, days, or weeks by specifying the first letter of any of those words (e.g., "1w").
Example2: Ansible Find files age within 30 days - Negative ageing
The Linux find Command
Here is the command that you would ideally execute in the Linux OS to find the files with age less than or equal to 30 days.
find /var/log -name "*.log" -type f -mtime -30
The Ansible Find AdHoc Command
The same Linux command can be rewritten as ansible ad hoc command as follows
ansible appgroup -i ansible_hosts -m find -a "paths='/var/log' file_type=file patterns='*.log' age=-30d"
Look at the following Comparision table between Linux Find and Ansible Find attributes.
I think this would give you a clear picture.
With Linux Find | With Ansible Find |
-type f | file_type=file |
find /var/log | paths='/var/log' |
-name "*.log" | pattern="*.log" |
-mtime -30 | age=-30d |
A Playbook with Ansible Find
The same can be put into the playbook as shown below.
---
- name: Ansible Find Example
hosts: testserver
tasks:
- name : Find files with age of less than 30 days
find:
paths: /var/log
patterns: '*.log'
age: -30d
register: output
- debug: var=item.path
with_items: "{{ output.files }}"
Example3: Recursively find the files by Size using Ansible Find
To find the files by size, Ansible find gives a parameter named size. Just like the Linux find command
The following playbook is to find all the files which are bigger than or equal to 100mb size.
The Linux find Command
Here is the command that you would ideally execute in the Linux OS to find the files with age less than or equal to 30 days.
find /var/log -name "*.log" -type f -size +100M
The Ansible Find AdHoc Command
The same Linux command can be rewritten as ansible ad hoc command as follows
ansible appgroup -i ansible_hosts -m find -a "paths='/var/log' file_type=file patterns='*.log' size=100m"
Look at the following Comparision table between Linux Find and Ansible Find attributes.
I think this would give you a clear picture.
With Linux Find | With Ansible Find |
-type f | file_type=file |
find /var/log | paths='/var/log' |
-name "*.log" | pattern="*.log" |
-size +100M | size=100m |
A Playbook with Ansible Find
The same can be put into the playbook as shown below.
---
- name: Ansible Find Example
hosts: testserver
tasks:
- name : Find files bigger than 100mb in size
become: true
find:
paths: /
file_type: file
size: 100m
recurse: yes
register: output
- debug: var=item.path
with_items: "{{ output.files }}"
Find the Smaller files than the Size Specified
To find the files which are lesser than the specified size, use the negative symbol at the front of the numeric value.
100m - would find the files grater than or equal to 100mb size
-100m - would find the smaller files with 100mb or below in size
Use of other size scales like GB, KB etc
If you want to use 100gb instead of 100mb, All you have to do is use
100g
instead of100m
same goes with kb
100k
and tb100t
Example4: Find All directories excluding few, as a list
In this example, we are going to see how to find only the directories. As you might have already guessed, we are going to use the file_type
parameter of ansible find to filter only the directories
In this example, we are also going to add all the matching directories into an array (or) list for better formatting.
Here is the playbook.
A Playbook with Ansible Find - to find the Directories alone
---
- name: Ansible Find Example
hosts: testserver
vars:
Files: []
tasks:
- name : Find files bigger than 100mb in size
become: true
find:
paths: /var/log
file_type: directory
recurse: no
excludes: 'nginx,mysql'
register: output
- name: Adding Files to the LIST
no_log: true
set_fact:
Files: "{{ Files + [item.path]}}"
with_items: "{{ output.files }}"
- debug: var=Files
In the playbook, You could see that we are having a three tasks. The first one is to find the directories. It is achieved by setting file_type: directory
we are having no recursive
as we do not want to traverse the subdirectories. In other words, we want only the directories of /var/log
we are excluding the directories named nginx and mysql
from the result.
In the next task. we are traversing through the output register variable captured in the previous task and just filtering the directory names alone and creating an array (or) list using set_fact
this is how you can create a dynamic variable in the playbook.
The output of this playbook would look like this. You can see the output is neat and formatte
Example5: Find Files with a Regex Pattern in Ansible find
Though we have used the patterns in the previous examples to find the files. They were not complex enough to match the real-world requirements. So we need some advanced patterns like regex
to find the files or directories we want.
Ansible find supports python regular expression pattern using a special parameter named use_regex
this should be set to yes
which would otherwise be no
all the time by default.
Here is the example playbook with the regular expression pattern
A Playbook with Ansible Find - to find files with regular expression
This playbook has a Single pattern to find the log files starting with letters and then numbers and end with .log
extension
The example matching file would be something like this filebeat_29122019.log
---
- name: Ansible Find Example
hosts: testserver
vars:
Files: []
tasks:
- name : Find files bigger than 100mb in size
become: true
find:
paths: /var/log
file_type: file
patterns: '^[a-z]*_[0-9]{8}\.log$'
size: 100m
use_regex: yes
register: output
- name: Adding Files to the LIST
no_log: true
set_fact:
Files: "{{ Files + [item.path]}}"
with_items: "{{ output.files }}"
- debug: var=Files
A Playbook with Ansible Find - with multiple regular expression
Sometimes, we might want to find various files with a different set of naming conventions. Instead of rewriting the patterns, we can use multiple patterns in a single play as shown below.
---
- name: Ansible Find Example
hosts: testserver
vars:
Files: []
tasks:
- name : Find files bigger than 100mb in size
become: true
find:
paths: /var/log
file_type: file
patterns:
- '^[a-z]*_[0-9]{8}\.log$'
- '^_[0-9]{2,4}_.*.log$'
- '^[a-z]{1,5}_.*log$'
size: 100m
use_regex: yes
register: output
- name: Adding Files to the LIST
no_log: true
set_fact:
Files: "{{ Files + [item.path]}}"
with_items: "{{ output.files }}"
- debug: var=Files
Example6: Ansible Find and Delete the files
Now you already know how to use Ansible Find to find the files you want using various filters and searching elements like time, size, etc.
Now let us see how to use Ansible find to delete the files once they are found
It is more like using xargs rm -rf
in linux find command
A Playbook with Ansible Find - Delete files with Ansible Find
---
- name: Ansible Find Example
hosts: testserver
tasks:
- name : Find files older than 30 days
become: yes
find:
paths: /var/log
patterns: '*.log'
age: 30d
age_stamp: mtime
register: output
- name: Delete the files matching
become: yes
file:
path: "{{item.path}}"
state: absent
with_items: "{{ output.files }}"
Here is the execution output of this playbook
I hope this article helps you understand the various uses of the Ansible find module.
For any questions feel free to comment
Cheers
Sarav AK
Follow me on Linkedin My Profile Follow DevopsJunction onFacebook orTwitter For more practical videos and tutorials. Subscribe to our channel
Signup for Exclusive "Subscriber-only" Content