Reputation: 3045
Here is my playbook where i try to find test-juli.jar
under /app
directory however, i wish to exclude /app/Patchbackup
folder from the search.
Below is my playbook for the same:
tasks:
- name: Find test home directories under /app
find:
paths: /app
file_type: any
recurse: yes
depth: 4
patterns: 'test-juli.jar'
excludes: 'log,tmp,.installation,Patchbackup'
tags: always
register: tomjarfound
- debug:
msg: "ALL LISTED REFINED JARS: {{ item.path }}"
loop: "{{ tomjarfound.files }}"
When i run the above, i was expecting the find
not to find under /app/Patchbackup
but the output shows that it does despite being excluded.
Here is the output:
TASK [debug] ***********************************************************************************************************************************************************
ok: [10.0.0.11] => (item=/app/apache-test-9.0.10/bin/test-juli.jar) => {
"msg": "ALL LISTED REFINED JARS: /app/apache-test-9.0.10/bin/test-juli.jar"
}
ok: [10.0.0.11] => (item=/app/Patchbackup/app/apache-test-9.0.10/bin/test-juli.jar) => {
"msg": "ALL LISTED REFINED JARS: /app/Patchbackup/app/apache-test-9.0.10/bin/test-juli.jar"
}
Can you please suggest how can I exclude the folder /app/Patchbackup
from ansible's find ?
Upvotes: 6
Views: 9014
Reputation: 6685
As you realized, the find
module doesn't provide you with an option to start with the root dir of /app
but exclude one of its directories. You have a few options:
/app
are not many, you can use the clause paths
to provide a list of them (excluding the undesired Patchbackup
)/app/Patchbackup
that you don't want. Here is an example of how to filter them out:Code:
- set_fact:
my_results_final: "{{ my_results_final | default([]) + [item] }}"
when: item is not regex('^/app/Patchbackup(.+)')
with_items:
- "{{ tomjarfound.files }}"
- debug:
var: my_results_final
Upvotes: 2
Reputation: 1
My solution to this omission is to go with json_query
filter:
- find:
paths: /app
recurse: true
patterns: 'test-juli.jar'
register: results
- set_fact:
final_result: "{{ results | to_json | from_json | json_query(_query) }}"
vars:
_query: "files[?!contains(path, 'Patchbackup')]"
you will need to have jmespath
python library installed. (if I remember it correctly that | to_json | from_json |
part is needed to deal with another types issue.
Upvotes: 0
Reputation: 3550
Ansible's find module's excludes
parameter operates on basenames of files. Per the documentation:
excludes: One or more (shell or regex) patterns, which type is controlled by use_regex option. Items whose basenames match an excludes pattern are culled from patterns matches. Multiple patterns can be specified using a list.
In your case, it is correctly ignoring /app/Patchbackup/
because its basename is Patchbackup
, but also correctly including /app/Patchbackup/app/apache-test-9.0.10/bin/test-juli.jar
because its basename is test-juli.jar
.
Upvotes: 3
Reputation: 311750
The find
module is arguably broken. The excludes
parameter applies only to items in the final result set, and not to intermediate directories.
That is, if you have a directory structure like this:
toplevel/
foo/
testfile1.txt
bar/
testfile2.txt
And from the parent of the toplevel
directory you run a task like this:
- find:
paths: toplevel
recurse: true
excludes: foo
register: results
Your result set will look like:
toplevel/bar/testfile2.txt
toplevel/foo/testfile1.txt
Compare that to setting file_type: any
, like this:
- find:
paths: toplevel
file_type: any
recurse: true
excludes: foo
register: results
In this case, the result set will look like:
- `toplevel/bar`
- `toplevel/bar/testfile2.txt`
- `toplevel/foo/testfile1.txt`
Note that toplevel/bar
is included in the results, but toplevel/foo
is excluded. That's because:
file_type: any
, which means we want to find directories as well as files.toplevel/foo
part of the result set.foo
You will get more flexible behavior if you simply use the find
command:
- name: exclude an intermediate directory with find command
command: >-
find toplevel -name foo -prune -o -type f -print
register: result
Which will return the following items:
toplevel/bar/testfile2.txt
I've put a runnable version of the above on github.
Upvotes: 6