35

Is there with_fileglob that works remotely in ansible?

Mainly I do want to use something similar with the with_fileglob but that will glob the files on the remote/target machine, not on the one that is running ansible.

sorin
  • 161,544
  • 178
  • 535
  • 806

4 Answers4

31

Use find module to filter the files and then process the resulting list:

- name: Get files on remote machine
  find:
    paths: /path/on/remote
  register: my_find

- debug:
    var: item.path
  with_items: "{{ my_find.files }}"
techraf
  • 64,883
  • 27
  • 193
  • 198
  • 2
    Worked well for `win_find` too. Thanks for the `with_items: "{{ my_find.files }}"` part, it is not obvious, I tried to use `with_items: my_find.files` at first. – QtRoS Feb 28 '19 at 12:44
23

All of the with_* looping mechanisms are local lookups unfortunately so there's no really clean way to do this in Ansible. Remote operations by design must be enclosed in tasks as it would need to deal with connections and inventory etc.

What you can do is generate your fileglob by shelling out to the host and then registering the output and looping over the stdout_lines part of the output.

So a trivial example may be something like this:

- name    : get files in /path/
  shell   : ls /path/*
  register: path_files

- name: fetch these back to the local Ansible host for backup purposes
  fetch:
    src : /path/"{{item}}"
    dest: /path/to/backups/
  with_items: "{{ path_files.stdout_lines }}"

This would connect to the remote host (e.g., host.example.com), get all the file names under /path/ and then copy them back to the Ansible host to the path: /path/host.example.com/.

Everett Toews
  • 10,337
  • 10
  • 44
  • 45
ydaetskcoR
  • 53,225
  • 8
  • 158
  • 177
  • In your experience, are there problems with line endings between Windows and Linux when you do this? E.g. would some `with_items` be blank copying stdout back from a `dir /b`? – Nic Sep 13 '17 at 00:55
4

Using ls /path/* didn't work for me, so here's an example that uses find and some simple regex to delete all nginx managed virtual hosts:

- name: get all managed vhosts
  shell: find /etc/nginx/sites-enabled/ -type f -name \*-managed.conf
  register: nginx_managed_virtual_hosts

- name: delete all managed nginx virtual hosts
  file:
    path: "{{ item }}"
    state: absent
  with_items: "{{ nginx_managed_virtual_hosts.stdout_lines }}"

You could use it to find all files with a specific extension or any other mix. For instance to simply get all files in a directory: find /etc/nginx/sites-enabled/ -type f.

Sebastiaan Luca
  • 486
  • 1
  • 8
  • 9
1

Here's a way to do it so that you can loop through all found. In my example, i had to look for all instances of pip to wipe out awscli in preparation to install awscli v2.0. I've done similar with lineinfile to strip out vars in /etc/skel dotfiles

- name: search for pip
  find:
    paths: [ /usr/local/bin, /usr/bin ]
    file_type: any
    pattern: pip*
  register: foundpip

- name: Parse out pip paths (say that 3 times fast)
  set_fact:
    pips: "{{ foundpip | json_query('files[*].path') }}"

- name: List all the found versions of pip
  debug:
    msg: "{{ pips }}"

#upgrading pip often leaves broken symlinks or older wrappers behind which doesn't affect pip but breaks playbooks so ignore!
- name: remove awscli with found versions of pip
  pip:
    name: awscli
    state: absent
    executable: "{{ item }}"
  loop: "{{ pips }}"
  ignore_errors: yes