Home Devops Checking if a file exists in Ansible

Checking if a file exists in Ansible

by The Linux Digest Guy
Ansible logo

There can be a slew of reasons you might want to check if a file exists in Ansible. At least in my case I often have to include a check in my ansible playbooks to see if a file or directory exists on the remote host. Most of the time it is to check if a certain action has already been performed by looking for configuration files.

But did you know you can perform a totally unrelated action based on the existence of a specific file or directory?

You can use the built-in stat module to check if a file exists in Ansible. Stat will look at the file and get its properties and state. You can then check if the file exists by looking at the resulting variable.

I have compiled a step-by-step guide below to get an understanding of how the stat module works. Keep reading to get the full experience.

Get the state of the file

First of all, we need to create a playbook to test the functionality. Below I have the beginning of the playbook. Please replace the host and user variables to fit your environment.

---

- name: check if myfile.txt exists
  hosts: testserver.linuxdigest.com
  user: root
  tasks:
    - name: Get stats about myfile.txt
      stat:
        path: /etc/myfile.txt
      register: myvar
    - debug:
        msg: "The contents of myvar: {{ myvar }}"

As you can see, we are checking for a file at the path /etc/myfile.txt. We tell Ansible to put the results of stat into a variable called myvar. After getting the information we want, we print what the variable now contains. Here is the output we get if the file exists:

Wow, that is a lot of information! Now we can see the permissions of the file, if it is a symlink when it was created, modified and a bunch of other stuff we don’t need right now. But, obviously, we can use the stat module to check for much more than just if the file exists.

But in this example, we only care about one value:

'stat': {'exists': True.....

We now know that the file exists. So now we just need to act on that information.

Perform action if the file exists

In the output above, the exists variable was within a dictionary called “stat”. So we can access the result with this path:

myvar.stat.exists

The value of this variable will be “True” if the file exists and “False” if it does not. We can now use the “when” conditional keyword with the action we want to take.

Now, let’s add an action. Just to test this premise, we will use the debug module to print a message if this file exists.

    - debug:
        msg: "The file myfile.txt exists!"
      when: myvar.stat.exists
    - debug:
        msg: "The file myfile.txt does not exists"
      when: myvar.stat.exists == False

This will print the correct line out, depending on if the file exists or not. Here is the output when the file exists:

We can see from the output, that the file exists. The second debug message is just skipped because it does not match.

Of course, we can perform any action that we want. Not just print the result. For example, we could install some piece of software if the file exists but uninstall it if it does not exist.

If for some reason, you wanted to make sure Apache is installed if the file exists, you could do something like this:

    - apt:
        name: apache2
        state: present
      when: myvar.stat.exists == True
    - apt:
        name: apache2
        state: absent
      when: myvar.stat.exists == False

Check if it is a file or directory

As we saw in the output of the stat module, we can check for other things than just the existence of the file.

It might be important to know if we are working with a file or a directory. For this we can check for the “isdir” variable. If the path is not a directory, the “isdir” variable might be undefined. So we need to verify if it exists before checking the value. Otherwise, we might get an error.

    - debug:
        msg: "myfile.txt is a directory!"
      when: myvar.stat.isdir is defined and myvar.stat.isdir

The simple way to create a file if it does not exist.

Just as a side note, you can also make sure a file exists with one command. I only include this in case somebody is using the stat module to create a file if it does not exist. Using the touch state in the file module. This way, the file will be created if it does not exist. Please note that if the file already exists it will be updated with a new modification date.

To skip updating the modification time and leave the file as is if it exists, you can add “modification_time: preserve”

- name: Touch a file. Creates the file if it does not exist. Otherwise, do nothing
  file:
    path: /etc/myfile.txt
    state: touch
    owner: root
    mode: 0644
    modification_time: preserve
    access_time: preserve

Possible return values from stat

The ansible stat module is quite powerful and can provide us with a lot of information about a file. So using it in your ansible playbook can be useful for other things than checking if a file exists. I have compiled a list of possible return values from the stat module in the table below.

VariableTypeDescription
atimefloatTime of last access
attributeslist of stringsList of file attributes
charsetstringCharacter or encoding of file
checksumstringHash of file
ctimefloatTime of last metadata update or creation (depends on OS)
devintegerDevice the inode is on
executeablebooleanTrue if the executable permission is set for the current user
existsbooleanTrue if the destination file exists
gidintegerFile owner’s group ID
gr_namestringFile owner’s group name
inodeintegerInode number of the path
isblkbooleanTrue if the path is a block device
ischrbooleanTrue if the path is a character device
islnkbooleanTrue if the path is a symbolic link
isregbooleanTrue if the path is a regular file
issockbooleanTrue if the path is a UNIX socket
isuidbooleanTrue if the current user is the owner
lnk_sourcestringTarget of the symlink if the file is a symbolic link
lnk_targetstringTarget of the symlink if the file is a symbolic link
mimetypestringFile magic data or mime-type
modestringUnix permissions of the file in octal. Ex. “0644”
mtimefloatTime of last modification
nlinkintegerNumber of hard links to the file
pathstringFull path
pw_namestringUsername of the owner
readablebooleanTrue if the invoking user has permission to read the path
rgrpbooleanTrue if the owner’s group has read permission
rothbooleanTrue if others have read permission
rusrbooleanTrue if the owning user has permission to read the path
sizeintegerSize of the file in bytes
uidintegerUID of the owner
versionstringVersion of the file according to the filesystem
wgrpbooleanTrue if the owner’s group has write permission
wothbooleanTrue if others have write permission
writeablebooleanTrue if the invoking user has write permission
wusrbooleanTrue if the owner has write permission
xgrpbooleanTrue if the owning user has executable permission
xothbooleanTrue if others have executable permission
xusrbooleanTrue if the owning user has executable permission

That’s it for now. I hope this helps. I will be writing more ansible tutorials in the future. In the meantime, you can check out some related articles here:

3

Related Posts

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More

Privacy & Cookies Policy