Ansible-查找并替换

Ansible-查找并替换,ansible,Ansible,用例 列出目录中的所有文件,格式为-a1.{{env}}.js,a2.{env}}.js 在目标目录中查找格式为-a1.js,a2.js 在存在a1.js的目录中复制a1.{{env}}.js,在存在a2.js的目录中复制a2.{env}}.js 示例代码:此代码执行直接查找和替换 -名称:在存档中查找文件 查找: 路径:“存档/” 文件类型:文件 递归:是的 寄存器:tmp_文件_路径 -名称:在存档中查找与名称匹配的代码中的文件 查找: 路径:“代码/” 文件类型:文件 递归:是的 模式:“

用例

  • 列出目录中的所有文件,格式为-
    a1.{{env}}.js
    a2.{env}}.js
  • 在目标目录中查找格式为-
    a1.js
    a2.js
  • 在存在
    a1.js
    的目录中复制
    a1.{{env}}.js
    ,在存在
    a2.js
    的目录中复制
    a2.{env}}.js
  • 示例代码:此代码执行直接查找和替换

    -名称:在存档中查找文件
    查找:
    路径:“存档/”
    文件类型:文件
    递归:是的
    寄存器:tmp_文件_路径
    -名称:在存档中查找与名称匹配的代码中的文件
    查找:
    路径:“代码/”
    文件类型:文件
    递归:是的
    模式:“{tmp_file_path.files | map(attribute='path')| map('basename')| list}”
    寄存器:代码\文件\路径
    -设定事实:
    code_文件:“{{code_文件|默认值([]))+
    [{'path':项,'name':项| basename}]}”
    循环:{code_file_path.files|map(attribute='path')|list}
    -名称:将文件从存档复制到代码目录
    命令:cp“{item.0}}”{{{item.1.path}”
    什么时候:
    -item.0 | basename==item.1.路径| basename
    与你一起:
    -“{tmp_file_path.files | map(attribute='path')| list | sort}”
    -“{code_files}排序(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
    文件夹复制的文件,
    path
    是所述文件应在其中找到其目的地的数组

  • 大部分逻辑由Ansible筛选器完成,该筛选器通过一个非常简单的表达式提取要在
    code
    文件夹中查找的文件名:

    item.path | basename | regex|u replace('(.*)\...*\.js$','\\1.js')
    
  • 这里使用的另一个过滤器可能是值得研究的过滤器,其参数为
    recursive=true
    ,它允许创建文件应该在其中找到目的地的
    路径

  • 这里还使用了一个Python操作:,以便创建逗号分隔的文件列表,以便从上面字典的键中搜索
    code
    文件夹中的文件

  • 它还利用过滤器的
    循环
    ,同时遍历字典及其子数组
    路径

  • 完整地说,以下是本手册中使用的其他更常用的过滤器:

    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 
    
    • :在未定义变量时指定默认值
    • :仅从文件的完整路径中获取文件名
    • :仅从文件的完整路径获取目录
    • :根据分隔符连接数组的元素
  • 是的,与您的用例相比,它可能设计过度,下面的playbook能够处理
    a1.js
    可能位于两个不同文件夹中的事实,并且能够在这两个文件夹中复制
    a1.test.js

  • 因此,这里有一个解决方案:

    -hosts:localhost
    收集事实:不
    任务:
    -查找:
    路径:存档
    文件类型:文件
    递归:是的
    登记:档案
    -设定事实:
    搜索:“{searches | default({})| combine({key:value})}”
    变量:
    键:“{item.path | basename | regex|u replace('(.*)\..*\.js$','\\1.js')}”
    值:“{{'archive':item.path,'path':[]}”
    循环:“{archives.files}}”
    回路控制:
    标签:“{item.path}”
    -查找:
    路径:代码
    文件类型:文件
    递归:是的
    模式:“{searches.keys()| join(',')}”
    寄存器:路径
    -设定事实:
    搜索:{searches | combine({key:value},recursive=true)}
    变量:
    键:{item.path | basename}}”
    值:“{{'paths':[item.path | dirname]+搜索[item.path | basename].paths}”
    循环:“{paths.files}}”
    回路控制:
    标签:“{item.path}”
    -副本:
    src:{{item.0.archive}}”
    dest:{item.1~'/'~item.0.archive | basename}
    循环:{{searches}子元素('path')}
    回路控制:
    标签:“{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
    

    关于该方法的一些解释:

  • 它的整个思想是建立在一个字典的基础上的,该字典指示剧本中应该在哪里添加文件。
    对于您的用例,字典如下所示:

    {
        "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
    文件夹复制的文件,
    path
    是所述文件应在其中找到其目的地的数组

  • 大部分逻辑由Ansible筛选器完成,该筛选器通过一个非常简单的表达式提取要在
    code
    文件夹中查找的文件名:

    item.path | basename | regex|u replace('(.*)\...*\.js$','\\1.js')
    
  • 这里使用的另一个可能值得探索的过滤器是fi