When using "use_regex: yes" and setting an excludes: without
specifying a pattern: the existing code passes the file-glob '*' to
the regex matcher. This results in an internal invalid-regex
exception being thrown.
This maintains the old semantics of a default match-all for pattern:
but switches the default to '.*' when use_regex is specified.
The code made sense as-is before excludes: was added (2.5). In that
case, it made no sense to set use_regex but *not* set a pattern.
However, with excludes: it now makes sense to only want to exclude a
given regex but not specify a specific matching pattern.
Closes: #50067
* moved change to new location
added changelog
* Update lib/ansible/modules/find.py
Co-authored-by: Ian Wienand <iwienand@redhat.com>
... | ... |
@@ -29,7 +29,7 @@ options: |
29 | 29 |
first letter of any of those words (e.g., "1w"). |
30 | 30 |
type: str |
31 | 31 |
patterns: |
32 |
- default: '*' |
|
32 |
+ default: [] |
|
33 | 33 |
description: |
34 | 34 |
- One or more (shell or regex) patterns, which type is controlled by C(use_regex) option. |
35 | 35 |
- The patterns restrict the list of files to be returned to those whose basenames match at |
... | ... |
@@ -41,6 +41,7 @@ options: |
41 | 41 |
- This parameter expects a list, which can be either comma separated or YAML. If any of the |
42 | 42 |
patterns contain a comma, make sure to put them in a list to avoid splitting the patterns |
43 | 43 |
in undesirable ways. |
44 |
+ - Defaults to '*' when C(use_regex=False), or '.*' when C(use_regex=True). |
|
44 | 45 |
type: list |
45 | 46 |
aliases: [ pattern ] |
46 | 47 |
elements: str |
... | ... |
@@ -375,7 +376,7 @@ def main(): |
375 | 375 |
module = AnsibleModule( |
376 | 376 |
argument_spec=dict( |
377 | 377 |
paths=dict(type='list', required=True, aliases=['name', 'path'], elements='str'), |
378 |
- patterns=dict(type='list', default=['*'], aliases=['pattern'], elements='str'), |
|
378 |
+ patterns=dict(type='list', default=[], aliases=['pattern'], elements='str'), |
|
379 | 379 |
excludes=dict(type='list', aliases=['exclude'], elements='str'), |
380 | 380 |
contains=dict(type='str'), |
381 | 381 |
read_whole_file=dict(type='bool', default=False), |
... | ... |
@@ -395,6 +396,16 @@ def main(): |
395 | 395 |
|
396 | 396 |
params = module.params |
397 | 397 |
|
398 |
+ # Set the default match pattern to either a match-all glob or |
|
399 |
+ # regex depending on use_regex being set. This makes sure if you |
|
400 |
+ # set excludes: without a pattern pfilter gets something it can |
|
401 |
+ # handle. |
|
402 |
+ if not params['patterns']: |
|
403 |
+ if params['use_regex']: |
|
404 |
+ params['patterns'] = ['.*'] |
|
405 |
+ else: |
|
406 |
+ params['patterns'] = ['*'] |
|
407 |
+ |
|
398 | 408 |
filelist = [] |
399 | 409 |
|
400 | 410 |
if params['age'] is None: |
... | ... |
@@ -251,3 +251,24 @@ |
251 | 251 |
# dir contents are considered until the depth exceeds the requested depth |
252 | 252 |
# there are 8 files/directories in the requested depth and 4 that exceed it by 1 |
253 | 253 |
- files_with_depth.examined == 12 |
254 |
+- name: exclude with regex |
|
255 |
+ find: |
|
256 |
+ paths: "{{ output_dir_test }}" |
|
257 |
+ recurse: yes |
|
258 |
+ use_regex: true |
|
259 |
+ exclude: .*\.ogg |
|
260 |
+ register: find_test3 |
|
261 |
+# Note that currently sane ways of doing this with map() or |
|
262 |
+# selectattr() aren't available in centos6 era jinja2 ... |
|
263 |
+- set_fact: |
|
264 |
+ find_test3_list: >- |
|
265 |
+ [ {% for f in find_test3.files %} |
|
266 |
+ {{ f.path }} |
|
267 |
+ {% if not loop.last %},{% endif %} |
|
268 |
+ {% endfor %} |
|
269 |
+ ] |
|
270 |
+- debug: var=find_test3_list |
|
271 |
+- name: assert we skipped the ogg file |
|
272 |
+ assert: |
|
273 |
+ that: |
|
274 |
+ - '"{{ output_dir_test }}/e/f/g/h/8.ogg" not in find_test3_list' |