I have a list of files in a particular directory as shown below:
david@host:~/jobs/process/workspace/files$ ls -lrth total 68K -rw-r--r-- 1 david david 7.8K Oct 1 11:10 golden_proc.init.1569953435497 -rw-r--r-- 1 david david 7.7K Oct 2 12:11 golden_proc.init.1570043494149 -rw-r--r-- 1 david david 7.7K Oct 2 20:15 golden_proc.init.1570072510929
Each file name ends with timestamp in it. Now I need to find one latest file which was modified or created just a minute back in ansible.
- If there is no file like that then return successfully from the ansible by logging “cannot find any file” if this is possible to do.
- If there is a file like that then copy that file to “/tmp” folder.
- If there are multiple files generated or modified in the last minute then use the latest one.
Is this possible to do in ansible? I saw there is a find module in ansible but not sure how can I make above things work using that module?
--- - name: Play 1 hosts: 127.0.0.1 tasks: - name: find the latest file find: paths=/var/lib/jobs/workspace/process/files file_type=file age=-{{ time_window }}m age_stamp=mtime register: files
Advertisement
Answer
This is definitely something possible, you are even close from the solution.
As you might have seen it doing a debug
of your find
already, the return of it contains a list of files
, this list would just be empty if you have no file.
So it become pretty easy to see when the list is empty with Jinja
- debug: msg: '{{ files.files if files.files|count > 0 else "cannot find any file" }}'
This syntax is using an inline if
as well as a count
filter.
Regarding the fact that you want the most recent file now, you can also use a set of Jinja filers: the filter sort
will help you sort the files by modification time, and the filter first
will help you get only the first element of you list.
- debug: msg: '{{ (files.files | sort(attribute="mtime", reverse=true) | first).path }}'
Now you just need to combine both in one long Jinja expression:
- debug: msg: '{{ (files.files | sort(attribute="mtime", reverse=true) | first).path if files.files|count > 0 else "cannot find any file" }}'
In order to copy the file, you will need one extra Jinja filter that is specific to Ansible and that is basename
, in order to get the name of the file out of its full path
- debug: msg: '{{ (files.files | sort(attribute="mtime", reverse=true) | first).path | basename if files.files|count > 0 else "cannot find any file" }}'
But you will also need the when
statement so your copy will be skipped if there is no matching file:
- name: Copy file, if found copy: src: '{{ (files.files | sort(attribute="mtime", reverse=true) | first).path }}' dest: '/tmp/{{ (files.files | sort(attribute="mtime", reverse=true) | first).path | basename }}' when: files.files|count > 0
A full working playbook for you to test:
--- - hosts: localhost connection: locale vars: var_files: - { 'name': 'a', 'time': 86400 } - { 'name': 'b', 'time': 30 } - { 'name': 'c', 'time': 20 } tasks: - name: creating a bunch of matching files file: path: '/data/{{ item.name }}' state: touch with_items: '{{ var_files }}' - name: aging those files file: path: '/data/{{ item.name }}' modification_time: '{{ "%Y%m%d%H%M.%S" | strftime( ( ansible_date_time.epoch | int ) - item.time ) }}' with_items: '{{ var_files }}' - name: find the latest file find: paths=/data file_type=file age=-1m age_stamp=mtime register: files - debug: msg: '{{ (files.files | sort(attribute="mtime", reverse=true) | first).path if files.files|count > 0 else "cannot find any file" }}' - name: Copy file, if found copy: src: '{{ (files.files | sort(attribute="mtime", reverse=true) | first).path }}' dest: '/tmp/{{ (files.files | sort(attribute="mtime", reverse=true) | first).path | basename }}' when: files.files|count > 0 - name: removing files to test the behaviour with no matching files file: path: '/data/{{ item.name }}' state: absent with_items: '{{ var_files }}' - name: find the latest file find: paths=/data file_type=file age=-1m age_stamp=mtime register: files - debug: msg: '{{ (files.files | sort(attribute="mtime", reverse=true) | first).path if files.files|count > 0 else "cannot find any file" }}' - name: Copy file, if found copy: src: '{{ (files.files | sort(attribute="mtime", reverse=true) | first).path }}' dest: '/tmp/{{ (files.files | sort(attribute="mtime", reverse=true) | first).path | basename }}' when: files.files|count > 0
And the corresponding output of that playbook
PLAY [localhost] ******************************************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************************************** ok: [localhost] TASK [creating a bunch of matching files] ******************************************************************************************************* changed: [localhost] => (item={'name': 'a', 'time': 86400}) changed: [localhost] => (item={'name': 'b', 'time': 30}) changed: [localhost] => (item={'name': 'c', 'time': 20}) TASK [aging those files] ************************************************************************************************************************ changed: [localhost] => (item={'name': 'a', 'time': 86400}) changed: [localhost] => (item={'name': 'b', 'time': 30}) changed: [localhost] => (item={'name': 'c', 'time': 20}) TASK [find the latest file] ********************************************************************************************************************* ok: [localhost] TASK [debug] ************************************************************************************************************************************ ok: [localhost] => { "msg": "/data/c" } TASK [Copy file, if found] ********************************************************************************************************************** changed: [localhost] TASK [removing files to test the behaviour with no matching files] ****************************************************************************** changed: [localhost] => (item={'name': 'a', 'time': 86400}) changed: [localhost] => (item={'name': 'b', 'time': 30}) changed: [localhost] => (item={'name': 'c', 'time': 20}) TASK [find the latest file] ********************************************************************************************************************* ok: [localhost] TASK [debug] ************************************************************************************************************************************ ok: [localhost] => { "msg": "cannot find any file" } TASK [Copy file, if found] ********************************************************************************************************************** skipping: [localhost] PLAY RECAP ************************************************************************************************************************************** localhost : ok=9 changed=4 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0