Ich versuche, den Namen des übergeordneten Verzeichnisses von Dateien abzurufen, die durch ein Muster identifiziert werden.
base/tool1/sub/test.log
base/tool2/abc/values.log
base/tool3/sub/test.log
Ich möchte den absoluten Pfad jedes Verzeichnisses erhalten, in dem sich test.log befindet. Das base/tool1/sub/
wären also base/tool3/sub/
die Übereinstimmungen, die ich als Ergebnis erhalten möchte.
- name: "Loop-Playbook"
hosts: all
tasks:
- name: "Filter File Matches"
find:
paths: "/base"
file_type: "file"
recurse: "yes"
patterns: "*test.log"
register: files_matched
- name: "Debug files_matched full"
debug:
var: files_matched.files
- name: "Debug files_matched items"
debug:
var: item.path | dirname
loop: "{{ files_matched.files| flatten(levels=1) }}"
loop_control:
label: "{{ item.path }}"
Ich denke, ich muss etwas wie Folgendes verwenden, {{ item.path | dirname }}
aber ehrlich gesagt habe ich keine Ahnung, WO ich das definieren muss.
Kann mir jemand helfen?
Antwort1
map() in Jinjakönnen Attribute extrahieren oder einen Filter auf eine Sequenz anwenden. Verwenden Sie beides, um die Suchergebnisse in einer Filterkette zu transformieren.
---
- name: "basename of find results"
hosts: localhost
gather_facts: False
vars:
testfiles:
- base/tool1/sub/test.log
- base/tool2/abc/values.log
- base/tool3/sub/test.log
tasks:
- name: "Set up test case"
block:
- tempfile:
state: directory
register: mktemp
- file:
path: "{{ ( mktemp.path ~ '/' ~ item ) | dirname }}"
state: directory
loop: "{{ testfiles }}"
- file:
path: "{{ mktemp.path ~ '/' ~ item }}"
state: touch
loop: "{{ testfiles }}"
- name: "Filter File Matches"
find:
paths: "{{ mktemp.path }}"
file_type: "file"
recurse: "yes"
# patterns is already matched against basename
# Do not use a wildcard in front, so only "test.log" matches
patterns: "test.log"
register: files_matched
- name: "Debug files_matched full"
debug:
var: files_matched.files
verbosity: 1
- name: "Directories found"
debug:
msg: "{{ testdirnames }}"
vars:
# map to extract an attribute
# map to apply a filter
# (it can do either)
# list filter to consume any generator object returned by Jinja
testdirnames: "{{ files_matched.files | map(attribute='path') | map('dirname') | list }}"
Ausgabe:
$ ansible-playbook sf1073762.yml
PLAY [basename of find results] **************************************************************************************
TASK [tempfile] ******************************************************************************************************
changed: [localhost]
TASK [file] **********************************************************************************************************
changed: [localhost] => (item=base/tool1/sub/test.log)
changed: [localhost] => (item=base/tool2/abc/values.log)
changed: [localhost] => (item=base/tool3/sub/test.log)
TASK [file] **********************************************************************************************************
changed: [localhost] => (item=base/tool1/sub/test.log)
changed: [localhost] => (item=base/tool2/abc/values.log)
changed: [localhost] => (item=base/tool3/sub/test.log)
TASK [Filter File Matches] *******************************************************************************************
ok: [localhost]
TASK [Debug files_matched full] **************************************************************************************
skipping: [localhost]
TASK [Directories found] *****************************************************************************************************
ok: [localhost] => {
"msg": [
"/tmp/ansible.Nc0b6i/base/tool1/sub",
"/tmp/ansible.Nc0b6i/base/tool3/sub"
]
}