Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extract file names without extension - Ansible

Tags:

ansible

I have a variable file in ansible like below

check:
       - file1.tar.gz
       - file2.tar.gz

while iterating it in tasks i am using {{item}}

with_items: - "{{check}}",

Is there a way to extract the filenames without extension while iterating? i.e i need file1 from file1.tar.gz and file2 from file2.tar.gz

like image 313
doc_noob Avatar asked May 21 '20 08:05

doc_noob


1 Answers

Ansible has as splitext filter but unfortunately it only splits the extension after the last dot.

The only solution to reliably achieve your requirement IMO is to extract the characters before the first dot using either the split() python method available on string objects or the regex_replace filter

The regexp solution is a bit of an overkill for your current requirement. Meanwhile it is very flexible as you can easily adapt it to more complex situations (matching a semantic version in the name, look for a particular pattern). Moreover, since it is a filter (vs a python native method for .split()), you can either use it:

  • while you loop, applying the filter on each item
  • before you loop applying it to the entire list with the map filter.

Here is an example for each solution in the below playbook:

---
- name: Extract file name without extension(s)
  hosts: localhost
  gather_facts: false

  vars:
    check:
      - file1.tar
      - file2.tar.gz
      - file3.tar.bz2.back
      - a_weird_file.name.with.too.many.dots

    file_regex: >-
      ^([^\.]*).*

  tasks:
    - name: use the split() function
      debug:
        msg: >-
          {{ item.split('.') | first }}
      loop: "{{ check }}"

    - name: Apply regex filter while looping
      debug:
        msg: >-
          {{ item | regex_replace(file_regex, '\1') }}
      loop: "{{ check }}"

    - name: Apply regex filter on list before loop
      debug:
        var: item
      loop: >-
        {{ check | map('regex_replace', file_regex, '\1') | list }}

Here is the result.

Note: for my own knowledge, I used the profile_task callback plugin when running the playbook. You will see that on this small list of files, each method has an equivalent performance

$ ansible-playbook playbook.yml 

PLAY [Extract file name without extension(s)] *************************************************

TASK [use the split() function] ************************************************************
Friday 02 April 2021  18:53:14 +0200 (0:00:00.019)       0:00:00.019 ********** 
ok: [localhost] => (item=file1.tar) => {
    "msg": "file1"
}
ok: [localhost] => (item=file2.tar.gz) => {
    "msg": "file2"
}
ok: [localhost] => (item=file3.tar.bz2.back) => {
    "msg": "file3"
}
ok: [localhost] => (item=a_weird_file.name.with.too.many.dots) => {
    "msg": "a_weird_file"
}

TASK [Apply regex filter while looping] ****************************************************
Friday 02 April 2021  18:53:14 +0200 (0:00:00.056)       0:00:00.075 ********** 
ok: [localhost] => (item=file1.tar) => {
    "msg": "file1"
}
ok: [localhost] => (item=file2.tar.gz) => {
    "msg": "file2"
}
ok: [localhost] => (item=file3.tar.bz2.back) => {
    "msg": "file3"
}
ok: [localhost] => (item=a_weird_file.name.with.too.many.dots) => {
    "msg": "a_weird_file"
}

TASK [Apply regex filter on list before loop] **********************************************
Friday 02 April 2021  18:53:14 +0200 (0:00:00.056)       0:00:00.132 ********** 
ok: [localhost] => (item=file1) => {
    "ansible_loop_var": "item",
    "item": "file1"
}
ok: [localhost] => (item=file2) => {
    "ansible_loop_var": "item",
    "item": "file2"
}
ok: [localhost] => (item=file3) => {
    "ansible_loop_var": "item",
    "item": "file3"
}
ok: [localhost] => (item=a_weird_file) => {
    "ansible_loop_var": "item",
    "item": "a_weird_file"
}

PLAY RECAP *********************************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Friday 02 April 2021  18:53:14 +0200 (0:00:00.057)       0:00:00.189 ********** 
=============================================================================== 
Apply regex filter on list before loop --------------------------------- 0.06s
Apply regex filter while looping --------------------------------------- 0.06s
use the split() function ----------------------------------------------- 0.06s 
like image 137
Zeitounator Avatar answered Nov 15 '22 10:11

Zeitounator