Ansible ファイルの親ディレクトリ名を検索する

Ansible ファイルの親ディレクトリ名を検索する

パターンによって識別されるファイルの親ディレクトリ名を取得しようとしています。

base/tool1/sub/test.log
base/tool2/abc/values.log
base/tool3/sub/test.log

test.log が見つかるすべてのディレクトリの絶対パスを取得したいです。したがって、base/tool1/sub/結果base/tool3/sub/として取得したい一致になります。

- 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 }}"

おそらく、次のようなものを使用する必要があると思います{{ item.path | dirname }}が、正直なところ、これをどこで定義する必要があるのか​​全くわかりません。

誰か助けてくれませんか?

答え1

Jinja の map()属性を抽出したり、シーケンスにフィルターを適用したりできます。両方を使用して、検索結果を 1 つのフィルター チェーンに変換します。

---
- 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 }}"

出力:

$ 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"
    ]
}

関連情報