Delete all old files, but keep newest 3 files for same file name and different path - ansible

Hi can i know how can i keep the latest 3 files based on file name and path. For instance i have
fileAbackup1.war, fileAbackup2.war, fileAbackup3.war, fileAbackup4.war
fileBbackup1.war, fileBbackup2.war, fileBbackup3.war, fileBbackup4.war
So i should keep
fileAbackup1.war, fileAbackup2.war, fileAbackup3.war
fileBbackup1.war, fileBbackup2.war, fileBbackup3.war
I know the part of finding files and deleting files older than x days. I already done the coding part. But i need have some filter to keep 3 backup files of same name of different path
Updated
Below is my ansible code
- name: Find files
find:
paths: "{{ remove_file_path }}"
use_regex: yes
patterns:
- '*.war.*.backup*'
- '{{ rar_file_name }}.rar.*.bakup*'
- '.*\..*\.\d+\.\d{4}-\d{2}-\d{2}#\d{2}:\d{2}:\d{2}~$'
age: 5d
recurse: yes
register: removeFile
- name: Delete files
file:
path: "{{ item.path }}"
state: absent
loop: "{{ removeFile.files }}"

The tasks below
- find:
paths: dir1
patterns: '*.war'
register: result
- set_fact:
my_files: "{{ result.files|
map(attribute='path')|
sort|
list }}"
- debug:
var: my_files[0:3]
give
my_files[0:3]:
- dir1/fileAbackup1.war
- dir1/fileAbackup2.war
- dir1/fileAbackup3.war
If you need the filenames only map the filter basename. For example
- set_fact:
my_files: "{{ result.files|
map(attribute='path')|
map('basename')|
sort|
list }}"
- debug:
var: my_files[0:3]
give
my_files[0:3]:
- fileAbackup1.war
- fileAbackup2.war
- fileAbackup3.war
Q: "Will it have file fileBbackup1.war, fileBbackup2.war, and fileBbackup3.war as well?"
A: Yes. It will. Create a dictionary of the lists. For example
- set_fact:
my_files: "{{ my_files|default({})|
combine({item: result.files|
map(attribute='path')|
map('basename')|
select('search', item)|
sort|
list}) }}"
loop:
- fileAbackup
- fileBbackup
- debug:
msg: "{{ item.value[0:3] }}"
loop: "{{ my_files|dict2items }}"
loop_control:
label: "{{ item.key }}"
give
ok: [localhost] => (item=fileAbackup) =>
msg:
- fileAbackup1.war
- fileAbackup2.war
- fileAbackup3.war
ok: [localhost] => (item=fileBbackup) =>
msg:
- fileBbackup1.war
- fileBbackup2.war
- fileBbackup3.war

This command will provide the information you need.
ls -1 *.war | sort -r | head -n -3
Explanation
ls -1 *.war | sort -r Performs a reverse sort and displays just the filenames
head -n -3 Displays all except the first 3
You can pipe this to the command that deletes the files or you can run the following
rm $(ls -1 | sort -r | head -n -3)

Related

How to find new files in a directory and divide/split file name with the version name at the filename?

I have a directory that contains files like der_azureData_Linux_x64_24.1.0.0.7.tar. I need to find out the latest file in that directory and split the file name into name and version.
Expected output
name: der_azureData_Linux_x64
version: 24.1.0.0.7
Playbook
I tried with the below playbook but it is not displaying the file name.
- hosts: localhost
gather_facts: no
tasks:
- find:
paths: "/root/ansible.temp/"
patterns: "*.tar"
recurse: yes
register: files_matched
- set_fact:
latest_files: "{{ latest_files | default([]) + [item.path] }}"
loop: "{{ files_matched.files | sort(attribute='mtime', reverse=true) }}"
when: "item.path | dirname not in latest_files | default([]) | map('dirname')"
##
# The loop_control is just there for validation purpose
##
loop_control:
label: "{{ '%Y-%m-%d %H:%M:%S' | strftime(item.mtime) }} {{ item.path }}"
- debug:
var: latest_files
- name: check the directories and locations
shell: |
f = {{ latest_files }} # loop over each file in current directory
name="${f%_*}" # trim from right to first '_'
register: name
- name: print values
debug:
msg: "filename {{ name.stdout }} "
Output as follow
TASK [check the directories and locations] **************************
changed: [localhost]
TASK [print values] *************************************************
ok: [localhost] => {
"msg": "filename "
}
How to find new files in a directory? ... I need to find out the latest file in that directory.
Given the test files
tree test
test
├── newest.yml
├── test_1.2.3.4.tar
└── test_2.3.4.5.tar
ls -al test*
-rw-r--r--. 1 user users 0 Jan 16 12:00 test_1.2.3.4.tar
-rw-r--r--. 1 user users 0 Jan 16 12:00 test_2.3.4.5.tar
a minimal example playbook
---
- hosts: localhost
become: false
gather_facts: false
tasks:
- name: Get files in a folder
find:
paths: "/home/{{ ansible_user }}/test"
patterns: "*.tar"
register: result
- name: Get newest file
set_fact:
LATEST: "{{ result.files | sort(attribute='mtime',reverse=true) | first }}"
- name: Show LATEST
debug:
msg: "{{ LATEST.path | basename }}"
will result into an output of
TASK [Show LATEST] ****
ok: [localhost] =>
msg: test_2.3.4.5.tar
Similar Q&A
Getting the newest filename in a directory in Ansible
How to divide or split file name with the version name at the filename?
You may then proceed further with
- name: Show VERSION only
debug:
msg: "{{ LATEST.path | basename | split('_') | last | splitext | first }}"
resulting into an output of
TASK [Show VERSION only] ****
ok: [localhost] =>
msg: 2.3.4.5
Similar Q&A
Extract file names without extension - Ansible
Filters Used
basename
first
last
split
splitext
Further Documentation
Using filters to manipulate data - Managing file names and path names

Keep 3 latest backups for a list of file names

I have few files for which I'd like to keep the 3 latest backups and delete the remaining ones if any.
Below is what I a have tried so far.
main.yml
- name: Find files
find:
paths: "{{ deletePath }}"
use_regex: yes
patterns:
- '.*\.(txt)\.\d+\.\d{4}-\d{2}-\d{2}#\d{2}:\d{2}:\d{2}~$'
- '.*\.(zip)\.\d{4}\d{2}\d{2}$'
age_stamp: mtime
recurse: yes
register: filesToDelete
- name: Dictionary of files by its kind
set_fact:
filesDelDict: "{{ filesDelDict|default({}) |
combine({item: filesToDelete.files |
sort(attribute='mtime', reverse = true) |
map(attribute='path') |
select('search', item) |
list}) }}"
with_items:
- "{{ listOfFiles }}"
vars.yml
deletePath:
- '/home/user/Desktop/folder1'
- '/home/user/Desktop/folder3'
- '/home/user/Desktop/folder2'
listOfFiles :
- 'fileA.txt'
- 'fileB.txt'
- 'fileC.txt'

Ansible list windows folder in D drive and sort the output by numeric order get the last element

I have folders like this in my windows machine. using ansible want to sort this app-* pattern folder and get the last element. from this example I want to get d:\app-9.7.8 in ansible variable
d:\app-1.0.3
d:\app-1.0.7
d:\app-2.0.4
d:\app-7.0.4
d:\app-9.7.8
This code list the folder, but not sure how to sort and get the last element.
- name: Find dir
win_find:
paths: D:\
recurse: no
file_type: directory
register: result
- name: Find dir
debug:
msg: "output {{ result.files }}"
I am getting the last element like this:
- name: set dir
set_fact:
mule_dir_list: "{{ result.files | sort(attribute='path') | map(attribute='path') | list }}"
when: "( result.files |length > 0 )"
- name: print dir
debug:
msg: "dir {{ mule_dir_list[-1] }}"

In Ansible ,can we loop through list of files and match content in file using lineinfile module

I have to find all config.xml on a server and produce the list on a given server.
Once we registered the files list, i have to check the content in each file on the list using Ansible
I tried to derive the paths for all config.xml
register them and print the list
Added the registered variable into lineinfile path
##Derive Config.xml path
- name: Find the location of xml file
shell: find {{ wlx_mount_point }} -maxdepth 1 -name {{xml_file}} | rev | cut -d '/' -f3- | rev
register: wlx_domain_home
ignore_errors: yes
- debug:
msg: "{{ wlx_domain_home.stdout_lines|list }}"
- name: check domain home directory exists
stat:
path: "{{ wlx_domain_home |list }}"
ignore_errors: true
- debug:
msg: "{{ wlx_domain_home.stdout_lines|list }}"
- name: "Ensure Logging Settings in config.xml"
lineinfile:
line: "{{ item.line }}"
regexp: "{{ item.regexp }}"
path: "{{ wlx_domain_home.stdout_lines|list }}/config/config.xml"
state: present
backrefs: yes
register: config.xml.Logging
with_fileglob: "{{ wlx_domain_home.stdout_lines|list }}/config/config.xml"
with_items:
- line: "<logger-severity>Info</logger-severity>"
regexp: "^logger-severity.*"
Expected results are , it has to look for lines in each file and loop through the list. ` Its printing the list and not able to find the content
"_ansible_ignore_errors": true, "msg": "Destination
[u'/appl/cmpas9/user_projects/pte-ipscasws',
u'/appl/bbb/user_projects/qa-ucxservices_bkp',
u'/appl/app/user_projects/weiss_apps12',
u'appl/view/user_projects/weiss_apps12_oldbkp',
u'appl/voc/user_projects/qa-voc']/config/config.xml does not exist !"
}
This is how i fixed the issue. Now it gives output
- name: find all weblogic domain paths
shell: find /tech/appl -type f -name config.xml
register: wlx_domain_config
- debug:
var: wlx_domain_config.stdout_lines
name: "Ensure allow-unencrypted-null-cipher Encryption Settings in config.xml"
shell: grep -i "" {{ item }}
with_items: "{{ wlx_domain_config.stdout_lines }}"
register: allowunencrypted
debug:
var: allowunencrypted.stdout_lines

Playbook where item.stat.exist not working

I have created playbook which will run on a remote host and check whether the files exist or not. I want to extract the only files which are not present on the remote host. But my playbook giving all paths whether they are present or not.
Playbook:-
- name: Playbook for files not present on remote hosts
hosts: source
gather_facts: false
vars:
Filepath: /opt/webapps/obiee/oracle_common/inventory/ContentsXML/comps.xml
tasks:
- name: Getting files location path
shell: grep -i "COMP NAME" {{ Filepath }} |sed 's/^.*INST_LOC="//'|cut -f1 -d'"' | sed '/^$/d;s/[[:blank:]]//g' // extract files from comps.xml
register: get_element_attribute
- name: check path present or not
stat:
path: "{{ item }}"
with_items:
- "{{ get_element_attribute.stdout_lines }}"
register: path_output
- name: path exists or not
set_fact:
path_item: "{{ item }}" # here i am getting the output as expected that's files not present on remote host
with_items: "{{ path_output.results }}"
register: final_output
when: item.stat.exists == False
- debug:
var: final_output # giving both output i.e. files present and absent
- name: Create a fact list
set_fact:
paths: "{{ final_output.results | map(attribute='item.item') | list }}" # i have add this condition " item.stat.exists == False' inside this stmt
- name: Print Fact
debug:
var: paths
The issue resolved by using below command:
- name: Create a fact list
set_fact:
paths: "{{ final_output.results | selectattr('item.stat.exists', 'equalto', false) | map(attribute='item.item') | list }}"
register: config_facts
The following query should get all the file names which don't exsist on the remote host and store them in the fact 'paths':
- name: Create a fact list
set_fact:
paths: "{{ final_output | json_query(query)}}"
vars:
query: "results[?(#._ansible_item_label.stat.exists==`false`)]._ansible_item_label.item"

Resources