59

I'm trying to use the result of Ansible find module, which return list of files it find on a specific folder.

The problem is, when I iterate over the result, I do not have the file names, I only have their full paths (including the name).

Is there an easy way to use the find_result items below to provide the file_name in the second command as shown below?

- name: get files
  find:
    paths: /home/me
    file_type: "file"
  register: find_result

- name: Execute docker secret create
  shell: docker secret create <file_name> {{ item.path }}
  run_once: true
  with_items: "{{ find_result.files }}"
U880D
  • 8,601
  • 6
  • 24
  • 40
toto
  • 1,197
  • 2
  • 15
  • 26

3 Answers3

106

basename filter?

{{ item.path | basename }}

There are also dirname, realpath, relpath filters.

Konstantin Suvorov
  • 65,183
  • 9
  • 162
  • 193
4

This question and accepted answer are great for the time they were written. However, I want to leave a note about the current preferred way of doing it.

https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html#migrating-to-loop

With the release of Ansible 2.5, the recommended way to perform loops is the use the new loop keyword instead of with_X style loops.

I've seen seen this common pattern evolve for such file-loop combinations.

- name: "Find python files in folder scripts"
  find:
    paths: "{{ playbook_dir }}/scripts"
    patterns: "*.py"
    file_type: "file"
  register: python_files

- name: "Execute those python scripts from the script folder"
  shell: "python {{ item.path | basename }}"
  args:
    chdir: "{{ playbook_dir }}/scripts"
  loop: "{{ python_files.files }}"
  loop_control:
    label: "{{ item.path | basename }}"

This loops over a certain type of files in a directory (python files) and takes a certain action with their filename (executes them), and using their filename is justified because chdir puts you in the directory where those files are.

It's important to use that same filename in loop_control because otherwise it prints item, which isn't just the absolute path, but a dozen other file properties which is completely unreadable.

This works, but it also ignores the motivations for the loop changes to Ansible in the first place. This also works, replacing 2 tasks with 1:

- name: "Execute python scripts from the script folder"
  shell: "python {{ item | basename }}"
  args:
    chdir: "{{ playbook_dir }}/scripts"
  with_fileglob: "{{ playbook_dir }}/scripts/*.py"
  loop_control:
    label: "{{ item | basename }}"

In this loop, item is the absolute path. You may prefer to print that, in which case lose the loop_control completely.

AlanSE
  • 2,597
  • 2
  • 29
  • 22
-1

You need to extract the filename from the file path, becomes much easy. In your case: {{find_result.path|basename}}

Mizkax
  • 55
  • 2
  • 8
  • 1
    The accepted answer to this question, which is three years old, appears to cover this. When adding a new answer to an older question be sure to point out what new aspect of the question it addresses. – Jason Aller Jun 30 '20 at 16:29