提问人:Ashar 提问时间:8/25/2020 最后编辑:Ashar 更新时间:5/28/2022 访问量:6672
Ansible 查找模块不会在搜索中排除文件夹
Ansible find module does not exclude folder in the search
问:
这是我的剧本,我试图在目录下找到,但是,我希望从搜索中排除文件夹。test-juli.jar
/app
/app/Patchbackup
以下是我的剧本:
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 }}"
当我运行上述内容时,我期望找不到下面,但输出显示尽管被排除在外,但它确实如此。find
/app/Patchbackup
输出如下:
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"
}
您能否建议如何从 ansible 的查找中排除该文件夹?/app/Patchbackup
答:
该模块可以说是坏了。该参数仅适用于最终结果集中的项,而不适用于中间目录。find
excludes
也就是说,如果您有这样的目录结构:
toplevel/
foo/
testfile1.txt
bar/
testfile2.txt
从目录的父级中,运行如下任务:toplevel
- find:
paths: toplevel
recurse: true
excludes: foo
register: results
结果集将如下所示:
toplevel/bar/testfile2.txt
toplevel/foo/testfile1.txt
将其与设置进行比较,如下所示:file_type: any
- find:
paths: toplevel
file_type: any
recurse: true
excludes: foo
register: results
在本例中,结果集将如下所示:
- `toplevel/bar`
- `toplevel/bar/testfile2.txt`
- `toplevel/foo/testfile1.txt`
请注意,它包含在结果中,但被排除在外。这是因为:toplevel/bar
toplevel/foo
- 我们设置 ,这意味着我们想要查找目录和文件。
file_type: any
- 这将成为结果集的一部分。
toplevel/foo
- 我们从结果中排除了任何带有 basename 的内容
foo
如果您仅使用以下命令,您将获得更灵活的行为:find
- name: exclude an intermediate directory with find command
command: >-
find toplevel -name foo -prune -o -type f -print
register: result
这将返回以下项目:
toplevel/bar/testfile2.txt
我已经在 github 上放置了上述的可运行版本。
正如你所意识到的,该模块没有为你提供一个选项,让你从根目录开始,但排除其目录之一。您有以下几种选择:find
/app
- 如果下面的目录不多,您可以使用该子句提供它们的列表(不包括不需要的
/app
paths
Patchbackup
) - 检索 /app 下的所有结果,然后从中筛选出不需要的结果。下面是如何过滤掉它们的示例:
/app/Patchbackup
法典:
- 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
评论
find
find
with_items
set_fact
grep
when
Ansible 的 find 模块的参数对文件的基名进行操作。根据文档:excludes
excludes:一个或多个(shell 或正则表达式)模式,哪种类型由 use_regex 选项控制。基名与排除模式匹配的项目将从模式匹配中剔除。可以使用列表指定多个模式。
在你的例子中,它被正确地忽略了,因为它的基名是 ,但也正确地包括,因为它的基名是 。/app/Patchbackup/
Patchbackup
/app/Patchbackup/app/apache-test-9.0.10/bin/test-juli.jar
test-juli.jar
评论
我对这个遗漏的解决方案是使用过滤器:json_query
- 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')]"
您需要安装 Python 库。(如果我没记错的话,需要该部分来处理另一种类型的问题。jmespath
| to_json | from_json |
评论