Using the Ansible find module to search for files/folder

Ansible find module is used when you need to retrieve a list of files in the remote server which matches some conditions like name, size, etc. You will have to provide the path(s) to the remote server where the search should be done. It also supports searching for directories and links. The module returns the list of matched files/directories. You don’t have to give the exact name either since the module supports the pattern matching using regex attribute.

In addition to these, the module also supports searching based on the age or size of the file/directory. And we can also specify multiple conditions to be checked.

You can store the output of the task in a variable. It is particularly useful when you need to delete files having the conditions mentioned above.

My directory structure

Path: /home/mdtutorials2/findmodule/examples
.
|____searchfile.yaml
|____file_outside.txt
|____test1
| |____file1.txt
| |____file2.txt
| |____file3.log

Finding all files that match a pattern

We can use the ‘find’ module to search for all files having a particular extension like ‘.log’, ‘.txt’, ‘.service’ etc. Or we can say the file name should contain a particular pattern. The pattern matching can be either the Linux file glob type or Python regex. You can control this behavior by use_regex attribute, which is set to false(file glob) by default.

The following example will search for all the files in the location given by the path parameter. But it does not check the subfolders. That means it will only return the file_outside.txt.

- hosts: all
  tasks:
  - name: Ansible find file examples
    find:
      paths: /home/mdtutorials2/findmodule/examples
      patterns: "*.txt"
      register: files_matched

  - debug:
      msg: "{{ files_matched.files }}"

Note: You should quote the values in the pattern parameter.

Note: By default, the find module does not check for hidden files. To check for a hidden file you need to set the ‘hidden’ parameter to True.

Finding all files that match a pattern including the subdirectories

If you need to check the subdirectories also for the files, then you can use the recurse parameter. By default, it is set to no.

The following example will return the files file_outside.txt, file1.txt and file2.txt.

- hosts: all
  tasks:
  - name: Ansible find files in subdirectory examples
    find:
      paths: /home/mdtutorials2/findmodule/examples
      patterns: "*.txt"
      recurse: yes
      register: files_matched_subdirectory

  - debug:
      msg: "{{ files_matched_subdirectory.files }}"

Retrieving a value from the returned value

If you need to retrieve some values from the returned output (like files_matched_subdirectory.files int he above example), you can do the following.

The below example will retrieve the path value of the first file returned. If multiple files were returned you can adjust the index number to get the desired value.

- hosts: all
  tasks:
  - name: Ansible Find Example
    find:
      paths: /Users/mdtutorials2/Documents/Ansible
      patterns: "*.txt"
    register: files_matched
  - debug:
      msg: "{{ files_matched.files[0].path }}"

Giving multiple patterns in a single find command

You can also provide multiple patterns in a single command. You can separate them with a comma. For example, if you need to find all the files having the .txt and .log extension then you can do the following. This will return the files file_outside.txt, file1.txt, file2.txt and file3.log.

- hosts: all
  tasks:
  - name: Ansible find files multiple patterns examples
    find:
      paths: /home/mdtutorials2/findmodule/examples
      patterns: "*.txt,*.log"
      recurse: yes

Using Python regex to match filename

Till now we were using the file globs to search for the filenames. We can also use the Python regex for this as already mentioned. You should set the use_regex parameter to true for that.

The following example will find all the files that have the pattern ‘file’ followed by a number. So it should return file1.txt, file2.txt and file3.txt.

- hosts: all
  tasks:
  - name: Ansible find files Python regex example
    find:
      paths: /home/mdtutorials2/findmodule/examples
      patterns: "file[\\d].txt"
      recurse: yes
      use_regex: yes
    register: files_to_delete

Note: You have to escape the backslash since we are using the double quotes. If you use the single quotes, then the escape is not needed. So the following can be used.

patterns: 'file[\d].txt'

Finding all files that are older than a specified time

Another use of the Ansible find module is to find all the files that are older than a given time. You can use the age parameter to give the required age. You can give the age in seconds, minute, hour, days and week by giving a number and the first letter of those words.

Note: You can mention whether the time is change time(ctime), modify time(mtime) or access time(atime) using “age_stamp” parameter. By default, it is ‘mtime’. For more details on the difference between these refer unixtutorial.org.

seconds: “5s” ->older than 5 seconds

minute: “3m” ->older than 3 minutes

hour: “2h” -> older than 2 hours

days: “5d” -> older than 5 days

week: “6w” -> older than 6 weeks

- hosts: all
  tasks:
  - name: Ansible find files older than 3 minutes
    find:
      paths: /Users/dnpmacpro/Documents/Ansible
      age: "3m"
    register: olderfiles

Finding all files that are older than a specified time

You can also search for the files that are newer than the given time. You just need to use the negative symbol in front of the age value.

The following example will return all the files that are newer than 5 hours.

- hosts: all
  tasks:
  - name: Ansible find files newer than 5 hours
    find:
      paths: /Users/dnpmacpro/Documents/Ansible
      age: "-3h"
    register: newerfiles

Finding all files that are larger than a size

You can search for files based on size using the size option. You can specify the size in bytes(b), kilobytes(k), megabytes(m), gigabytes(g), and terabytes(t).

The following task returns all files that are larger than 5 megabytes.

- hosts: all
  tasks:
  - name: Ansible find files larger than 5 MB
    find:
      paths: /Users/dnpmacpro/Documents/Ansible
      size: "5m"
    register: largerfiles

Finding all files that are smaller than a size

You can also search for files smaller than a size by giving the negative of the value.

The following task returns all files that are larger than 5 kilobytes.

- hosts: all
  tasks:
  - name: Ansible find files larger than 100 KB
    find:
      paths: /Users/dnpmacpro/Documents/Ansible
      size: "100k"
    register: smallerfiles

Finding directories that match a pattern

All the above options can be used to search for directories also. There is the file_type parameter which you can set to ‘directory’ to specify the search is for directories only. By default, the value is ‘file’.

The below task returns all directories older than 50 days.

- hosts: all
  tasks:
  - name: Ansible find directories older than 50 days
    find:
      paths: /Users/dnpmacpro/Documents/Ansible
      age: "50d"
      file_type: directory
    

Storing the file names in a register

All these are useful when you can use the returned files for some tasks like deleting them. The return value can be stored in a variable and using the variable.files we can iterate through the list.

For more examples on using the find module to delete files and directories refer delete tutorial.

For example, if you need to delete all files with .log extension, which are older than 100 days, you can do the following.

- hosts: all
  tasks:
  - name: Ansible delete files examples
    find:
      paths: /home/mdtutorials2/findmodule/examples
      patterns: "*.log"
      age: "100d"
      recurse: yes
      register: files_to_delete

  - name: Ansible delete file glob
    file:
      path: "{{ item.path }}"
      state: absent
    with_items: "{{ files_to_delete.files }}"