簡體   English   中英

Ansible - 查找和替換

[英]Ansible - Find and Replace

用例

  1. 列出目錄中的所有文件,格式為 - a1.{{ env }}.js , a2.{{ env }}.js
  2. 在目標目錄中查找對應的文件,格式為 - a1.js , a2.js
  3. a1.{{ env }}.js復制到a1.js所在目錄,將a2.{{ env }}.js復制到a2.js所在目錄

示例代碼:此代碼直接查找和替換

- name: Find files in archive
  find:
    paths: "archive/"
    file_type: file
    recurse: yes
  register: tmp_file_path

- name: Find files in code matching names in archive
  find:
    paths: "code/"
    file_type: file
    recurse: yes
    patterns: "{{ tmp_file_path.files | map(attribute='path') | map('basename') | list }}"
  register: code_file_path

- set_fact:
    code_files: "{{ code_files|default([]) +
                    [{'path': item, 'name': item|basename}] }}"
  loop: "{{ code_file_path.files|map(attribute='path')|list }}"

- name: Copy files from archive to code directory
  command: cp "{{ item.0 }}" "{{ item.1.path }}"
  when:
    - item.0|basename == item.1.path|basename
  with_together:
    - "{{ tmp_file_path.files|map(attribute='path')|list|sort }}"
    - "{{ code_files|sort(attribute='name') }}"

下面列出的是目錄結構

├── archive
│   ├── a1.test.js
│   ├── a2.test.js
│   ├── a3.test.js
│   └── a4.test.js
└── code
    ├── a1.js
    ├── dir1
    │   └── a2.js
    └── dir2
        ├── a4.js
        └── dir3
            └── a3.js
  • archive/a1.test.js復制到code/
  • archive/a2.test.js復制到code/dir1/
  • archive/a3.test.js復制到code/dir1/dir2/dir3/
  • archive/a4.test.js復制到code/dir1/dir2/

是否有根據上述用例進行直接復制的解決方案?

關於該方法的一些解釋:

  1. 它的整個想法是基於創建一個字典來指示劇本應該在哪里添加哪個文件。
    對於您的用例,字典如下所示:

     { "a1.js": { "archive": "archive/a1.test.js", "paths": [ "code" ] }, "a2.js": { "archive": "archive/a2.test.js", "paths": [ "code/dir1" ] }, "a3.js": { "archive": "archive/a3.test.js", "paths": [ "code/dir1/dir2/dir3" ] }, "a4.js": { "archive": "archive/a4.test.js", "paths": [ "code/dir1/dir2" ] } }

    密鑰是我們在code文件夾下搜索的文件,密鑰archive表示我們打算從archive文件夾復制的文件, paths是一個數組,所述文件應該在其中找到其目的地。

  2. 大部分邏輯由 Ansible 過濾器regex_replace完成,它通過一個非常簡單的表達式提取文件名以在code文件夾中查找: (.*)\..*\.js$

     item.path | basename | regex_replace('(.*)\\..*\\.js$', '\\1.js')
  3. 此處使用的另一個可能值得探索的過濾器是combine過濾器,其參數為recursive=true ,它允許創建文件應找到其目的地的paths

  4. 還有一個 Python 操作在這里使用: dict.keys() ,以便從上面的字典的鍵中創建要在code文件夾中搜索的逗號分隔的文件列表。

  5. 它還利用帶有subelement過濾器的loop ,同時遍歷字典及其子數組paths

  6. 為了完整起見,以下是本劇本中使用的其他更常用的過濾器:

    • default :在未定義變量時指定默認值
    • basename :僅從完整路徑中獲取文件的名稱
    • dirname :僅從文件的完整路徑中獲取目錄
    • join :在這里,基於分隔符連接數組的元素
  7. 是的,與您的用例相比,它可能過度設計,下面的劇本能夠處理a1.js可能位於兩個不同文件夾中並且能夠在這兩個文件夾中復制a1.test.js的事實文件夾。

所以,這里有一個解決方案:

- hosts: localhost
  gather_facts: no

  tasks:
    - find:
        paths: archive
        file_type: file
        recurse: yes
      register: archives

    - set_fact:
        searches: "{{ searches | default({}) | combine({ key: value }) }}"
      vars: 
        key: "{{ item.path | basename | regex_replace('(.*)\\..*\\.js$', '\\1.js') }}"
        value: "{{ { 'archive': item.path, 'paths': [] } }}"   
      loop: "{{ archives.files }}"
      loop_control:
        label: "{{ item.path }}"

    - find:
        path: code
        file_type: file
        recurse: yes
        pattern: "{{ searches.keys() | join(',') }}"
      register: paths

    - set_fact: 
        searches: "{{ searches | combine({key: value}, recursive=true) }}"
      vars:
        key: "{{ item.path | basename }}"
        value: "{{ { 'paths': [item.path | dirname] + searches[item.path | basename].paths } }}"
      loop: "{{ paths.files }}"
      loop_control:
        label: "{{ item.path }}"

    - copy:
        src: "{{ item.0.archive }}"
        dest: "{{ item.1 ~ '/' ~ item.0.archive | basename }}"
      loop: "{{ searches | subelements('paths') }}"
      loop_control:
        label: "{{ item.0.archive }}"

之前的情況:

tree archive code
archive
├── a1.test.js
├── a2.test.js
├── a3.test.js
└── a4.test.js
code
├── a1.js
└── dir1
    ├── a2.js
    └── dir2
        ├── a4.js
        └── dir3
            └── a3.js

3 directories, 8 files

劇本回顧:

PLAY [localhost] **************************************************************************************************

TASK [find] *******************************************************************************************************
ok: [localhost]

TASK [set_fact] ***************************************************************************************************
ok: [localhost] => (item=archive/a3.test.js)
ok: [localhost] => (item=archive/a2.test.js)
ok: [localhost] => (item=archive/a1.test.js)
ok: [localhost] => (item=archive/a4.test.js)

TASK [find] *******************************************************************************************************
ok: [localhost]

TASK [set_fact] ***************************************************************************************************
ok: [localhost] => (item=code/a1.js)
ok: [localhost] => (item=code/dir1/a2.js)
ok: [localhost] => (item=code/dir1/dir2/a4.js)
ok: [localhost] => (item=code/dir1/dir2/dir3/a3.js)

TASK [copy] *******************************************************************************************************
changed: [localhost] => (item=archive/a3.test.js)
changed: [localhost] => (item=archive/a2.test.js)
changed: [localhost] => (item=archive/a1.test.js)
changed: [localhost] => (item=archive/a4.test.js)

PLAY RECAP ********************************************************************************************************
localhost                  : ok=5    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

之后的情況:

tree code
code
├── a1.js
├── a1.test.js
└── dir1
    ├── a2.js
    ├── a2.test.js
    └── dir2
        ├── a4.js
        ├── a4.test.js
        └── dir3
            ├── a3.js
            └── a3.test.js

3 directories, 8 files

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM