An Ansible playbook can fail or behave unpredictably if a file path is missing or permissions are incorrect. You can use the stat module to check files and directories before running an automated workflow on a remote system.
This guide will show you how to use stat to retrieve file details and control how tasks in your playbook run.

Prerequisites
- Access to the command line.
- Ansible installed and configured (see our guides on installing Ansible on Ubuntu, Rocky Linux, and Windows).
- A reachable remote host.
What Is the Ansible stat Module?
The Ansible stat module is a built-in tool that retrieves metadata about files and directories on remote systems. The collected data is stored in a variable that you can later use in your playbook to decide how tasks should run.
With stat, you can introduce conditional logic into your playbooks. For example, you can:
- Check if a file exists and run tasks based on the result.
- Skip configuration steps if a file is already up to date.
- Change file or directory permissions if they are incorrect.
- Detect file changes using checksums.
- Verify file ownership before making changes.
Keep in mind that stat is a read-only module. It only collects data and cannot make changes. To create or modify files in Ansible, you still need to rely on other modules, like file, copy, or template.
Ansible Stat Module Syntax
This is the basic syntax for using the stat module:
- name: The name of your playbook
hosts: all
tasks:
- name: The name of the task
stat:
path: /path/to/file_or_directory
register: file_data
In this example:
statline tells Ansible to use thestatmodule.pathdeclares the path to the file or directory you want to check.registerstores the output of thestatmodule in thefile_datavariable.
The variable name file_data is just a placeholder and can be replaced with any name you prefer.
Ansible Stat Output
This is a basic example of the stat module output:
file_data:
changed: false
stat:
exists: true
isreg: true
isdir: false
mode: "0644"
size: 1024
uid: 1000
gid: 1000
pw_name: nginx
gr_name: nginx
mtime: 1773878400
You can reference this data in the playbook using the following format:
file_data.stat.[attribute]
For example, if you want to add logic based on file size, use the size attribute:
file_data.stat.size
System administrators usually focus on the following metadata values:
| Attribute Name | Description | Example Value |
|---|---|---|
exists | Shows if a file or directory exists. | true |
isreg | Tells you if the path points to a regular file (not a directory or symlink). | true |
isdir | Indicates whether the specified path is a directory. | false |
mode | Displays the file's permission settings | 0644 |
size | The size of the file in bytes. | 1024 |
uid | The numeric user ID of the file owner. | 1000 |
gid | The numeric group ID of the file. | 1000 |
pw_name | Username of the file owner. | nginx |
gr_name | Group name of the file owner. | nginx |
mtime | The Unix timestamp that shows when the file was last modified. | 1773878400 |
In practice, most playbooks only include a few key values, such as exists, mode, and isdir.
Ansible Stat Parameters
You can use stat parameters to define what information the module collects and how it behaves. The most commonly used parameters include:
| Parameter | Description |
|---|---|
path | The path to the file or directory you want to inspect. This is the only required stat parameter. |
follow | Controls how Ansible handles symbolic links. The default value (no) tells Ansible to inspect the link itself. If you set it to yes, Ansible will follow the link and check the target file. |
get_checksum | Calculates the checksum of the file. It is enabled by default, but you can set it to no when working with large files or when checksum data is not needed. |
get_mime | Returns MIME type information about the file. |
checksum_algorithm | Lets you choose which algorithm, for example, sha1 or sha256, to use for file checksums. |
In most cases, you only need the path parameter. The others are useful if you need tighter control over how Ansible checks the file.
Ansible Stat Examples
The following section covers some of the most common ways the stat module is used in playbooks.
Check If a File Exists
The exists value shows if a file or directory exists at the specified path. In playbooks, it's often used to control other tasks.
For example, you can use it with the copy module and a when condition to create a file only if it does not exist:
- name: Check if the file exists
stat:
path: /home/some_directory/test.yml
register: file_data
- name: Create the file only if it does not exist
copy:
src: test.yml
dest: /home/some_directory/test.yml
when: not file_data.stat.exists
When you run the playbook:
1. The stat module checks if /home/some_directory/test.yml exists on the remote host.
2. The result is stored in the file_data variable. Within this variable, the file_data.stat.exists value is either true or false.
3. The when condition checks this value. If it evaluates to true, the file exists, and the copy task is skipped.
4. If file_data.stat.exists is false, the file does not exist, and the copy task runs and creates it from the source file.
You can use the copy module on its own, but if the source content is different, it will overwrite the file. Using the stat module with a when condition prevents the task from running if the file already exists.
Note: Ansible playbooks use YAML. If you have not worked in YAML before, learning its basic syntax will make it easier to read and write playbooks and follow the examples in this guide.
Display File Information
The metadata from stat can help you troubleshoot a playbook or check file properties before setting a condition. To display detailed information about a file or directory in your terminal, use the debug module:
- name: Get file information
stat:
path: /home/some_directory/test.yml
register: file_data
- name: Display file information
debug:
var: file_data.stat
In this playbook example:
1. The first task uses the stat module to collect information about the test.yml file and stores the data in the file_data variable.
2. The second task uses the debug module to access the file_data.stat object and print the stored values to the terminal.
The output includes the size, permissions, ownership, and other metadata relevant to the test.yml file. For instance:
file_data:
stat:
exists: true
isreg: true
mode: "0644"
size: 1024
pw_name: nginx
This is a basic example. The actual output may include additional attributes depending on the file and your system.
Access File Metadata
You can access any attribute in a stat object. Instead of working with all returned values, select the ones you need and use them in your playbook.
To do this, use the registered variable in the following format:
file_data.stat.[attribute]
For example:
- name: Get file information
stat:
path: /home/some_directory/test.yml
register: file_data
- name: Fix file permissions if incorrect
file:
path: /home/some_directory/test.yml
mode: "0644"
when: file_data.stat.mode != "0644"
Once you run the playbook:
1. The first task uses the stat module to collect information about /home/example_directory/test.yml.
2. The results are stored in the file_data variable. Inside this variable, the file_data.stat.mode value stores the current file permissions.
3. The when condition checks this value by comparing it to "0644". If the current permissions do not match, the condition evaluates to true.
4. If the condition evaluates to true, the file module runs and updates the file's permissions. Otherwise, the task is skipped.
Note: If you want to avoid making changes on a remote system right away, run your playbook in a dry run (check mode). This shows you what Ansible would do before any changes are made.
Reuse File Metadata
The stat module stores metadata in a variable. This allows you to reuse the data in multiple tasks within the same play without running the same check again.
In this example, the same metadata is reused in two different tasks:
- name: Get file information
stat:
path: /home/some_directory/test.yml
register: file_data
- name: Fix the permissions if needed
file:
path: /home/some_directory/test.yml
mode: "0644"
when: file_data.stat.mode != "0644"
- name: Restart service if the file exists
service:
name: test_app
state: restarted
when: file_data.stat.exists
When you run the playbook:
1. The stat module runs once and stores the result in the file_data variable.
2. The second task uses the file module with a when condition to check the file's permissions in file_data.stat.mode.
3. If the permissions are wrong, the task runs and updates them. If they are already correct, the task is skipped.
4. The third task uses the service module and another when condition to check the file_data.stat.exists value from the same metadata.
5. If this value is true, the file exists, and the service module restarts the test_app service.
6. If file_data.stat.exists is false, the file does not exist, so the task is skipped.
Note: Ansible is a popular Infrastructure-as-Code (IaC) tool. Learning what problems IaC solves and its best practices can help you design more reliable playbooks.
Combining Conditional Checks
When you use the stat module together with the when condition, you can control when tasks run. By combining several conditions into a single task, you can create more precise logic and keep your playbooks tidy and easy to follow.
For example, this play restarts a service only if the file meets certain conditions:
- name: Check file state
stat:
path: /home/some_directory/test.yml
register: file_data
- name: Deploy file if it does not exist
copy:
src: test.yml
dest: /home/some_directory/test.yml
mode: "0644"
when: not file_data.stat.exists
- name: Fail if file is empty
fail:
msg: "The file exists, but it is empty!"
when: file_data.stat.exists and file_data.stat.size == 0
- name: Restart service if the file is valid
service:
name: test_app
state: restarted
when: file_data.stat.exists and file_data.stat.isreg and file_data.stat.size > 0
This is what happens when you run the playbook:
1. The stat module runs once and stores metadata about /home/some_directory/test.yml in the file_data variable.
2. The second task checks if the file exists. If it does not exist, the copy module creates it.
3. The third task checks if the file is empty. If file_data.stat.exists is true and file_data.stat.size is 0, the playbook stops and displays an error message.
4. The last task uses the when condition to check if the file exists, whether it is a regular file, and finally, if it has any data.
5. The service restarts only if all these conditions are met. If not, the task is skipped.
Note: The registered variables used in this guide are created at runtime. If you want to learn more about variables, facts, and conditions in Ansible, see our complete guide on Ansible variables.
Conclusion
After working through these stat module examples, you can now add conditional logic to your playbooks. This makes your plays more precise and efficient when working with files and directories.
If you want to run Ansible at scale, phoenixNAP's Bare Metal Cloud (BMC) integrates directly with Ansible through the Bare Metal Cloud plugin.



