[英]Ansible - Find and Replace
用例
a1.{{ env }}.js
, a2.{{ env }}.js
a1.js
, a2.js
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/
是否有根據上述用例進行直接復制的解決方案?
關於該方法的一些解釋:
它的整個想法是基於創建一個字典來指示劇本應該在哪里添加哪個文件。
對於您的用例,字典如下所示:
{ "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
是一個數組,所述文件應該在其中找到其目的地。
大部分邏輯由 Ansible 過濾器regex_replace
完成,它通過一個非常簡單的表達式提取文件名以在code
文件夾中查找: (.*)\..*\.js$
item.path | basename | regex_replace('(.*)\\..*\\.js$', '\\1.js')
此處使用的另一個可能值得探索的過濾器是combine
過濾器,其參數為recursive=true
,它允許創建文件應找到其目的地的paths
。
還有一個 Python 操作在這里使用: dict.keys()
,以便從上面的字典的鍵中創建要在code
文件夾中搜索的逗號分隔的文件列表。
它還利用帶有subelement
過濾器的loop
,同時遍歷字典及其子數組paths
。
為了完整起見,以下是本劇本中使用的其他更常用的過濾器:
是的,與您的用例相比,它可能過度設計,下面的劇本能夠處理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.