Find files in a loop and delete them

Viewed 418

I would like to delete file in some sub directory which contains certain format. However, I am getting the error

'dict object' has no attribute 'files'.

Below is my code. The file pattern would be file_name.file_extension.processID.YYYY-MM-DD@HH:MM:SS~

My variables

fileToFindInAllSubDirecotry
  - "home/usr/file1"
  - "home/usr/file2"
  - "home/usr/file3/file4"
  - "home/usr/file5"

My playbook role

- name: Find file
  find:
    paths: "{{ item }}"
    use_regex: yes
    patterns:
      - '.*\.\d+\.\d{4}-\d{2}-\d{2}@\d{2}:\d{2}:\d{2}~$'
    age: 1d
    recurse: yes
  register: fileToDelete
  loop: "{{ fileToFindInAllSubDirecotry }}"
  
- name: Delete file
  file:
    path: "{{ item.path }}"
    state: absent
  loop: "{{ fileToDelete.files }}"

This is the sample file and directory

home
   |-------usr
             |-------file1
                         |-------configFile.xml
             |-------file2
                         |-------propertiesFile.txt.2012.2020-07-13@23:08:10~
             |-------file3
                         |-------file4
                                     |-------content.yml.2012.2020-04-04@23:08:10~                       
             |-------file5
                         |-------configFile.xml.2012.2020-03-05@13:08:10~
1 Answers

This is happening because you are populating the find with a loop, so you end up with a result that would be a dictionary having a list or results.

Something like:

ok: [localhost] => {
    "msg": {
        "changed": false,
        "msg": "All items completed",
        "results": [
            {
                ...
                "files": [ ... ],
                ...
                "item": "/home/usr/file1",
                ...
            },
            {
                ...
                "files": [ ... ],
                ...
                "item": "/home/usr/file2",
                ...
            },
            ...
        ]
    }
}

There is two ways to fix this:

  1. The nicest one, because, as pointed by the documentation, the paths parameter of the module find can accept lists of paths, just pass it your whole fileToFindInAllSubDirecotry variables instead of using a loop, this way your deletion works as is:

    - name: Find file
      find:
        paths: "{{ fileToFindInAllSubDirecotry }}"
        use_regex: yes
        patterns:
          - '.*\.\d+\.\d{4}-\d{2}-\d{2}@\d{2}:\d{2}:\d{2}~$'
        age: 1d
        recurse: yes
      register: fileToDelete
    
    - name: Delete file
      file:
        path: "{{ item.path }}"
        state: absent
      loop: "{{ fileToDelete.files }}"
    
  2. Use json_query to fetch the result[*].files then flatten the resulting list of list

    - name: Find file
      find:
        paths: "{{ item }}"
        use_regex: yes
        patterns:
          - '.*\.\d+\.\d{4}-\d{2}-\d{2}@\d{2}:\d{2}:\d{2}~$'
        age: 1d
        recurse: yes
      register: fileToDelete
      loop: "{{ fileToFindInAllSubDirecotry }}"
    
    - name: Delete file
      file:
        path: "{{ item.path }}"
        state: absent
      loop: "{{ fileToDelete | json_query('results[*].files') | flatten }}"
    
Related