AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 745257
Accepted
Sollosa
Sollosa
Asked: 2023-05-08 16:32:39 +0800 CST2023-05-08 16:32:39 +0800 CST 2023-05-08 16:32:39 +0800 CST

ansible比较2个目录中的所有文件并打印差异

  • 772

我有2个目录

$ tree dir{1..2}
dir1
├── file1
└── file2
dir2
├── file1
└── file2

我想使用 ansible 将 dir1 中的所有文件与 dir2 中的所有文件进行比较,并像这样打印差异

output:
${file1} from ${dir1}:
diff content

${file1} from ${dir2}:
diff content

它将遍历所有文件以打印它们的差异

下面是需要修改的ansible片段

---
- name: Compare files in two directories
  hosts: localhost
  gather_facts: false
  tasks:
    - name: Find files in directory 1
      find:
        paths: ~/dir1
        file_type: file
      register: dir1_files

    - name: Find files in directory 2
      find:
        paths: ~/dir2
        file_type: file
      register: dir2_files

    - name: Compare files
      shell: diff dir1/file1 dir2/file1 ## how can I make sure path changes but filenames stay same using variables
      loop: "{{ dir1_files.files }}"
      register: diff_output
      changed_when: false
      failed_when: diff_output.rc == 1

    - name: Print differences
      debug:
        msg: |
          {{ item.item.path }} from dir1:
          {{ item.stdout }}
          {{ item.item.path }} from dir2:
          {{ item.stdout }}
      loop: "{{ diff_output.results }}"
      when: item.stdout_lines | length > 0

对于 Vladimir 的回答中的建议代码,我得到以下输出

TASK [debug] *****************************************************************************************************************************************
ok: [localhost] => {
    "msg": "file2 from dir1: \n  1,2c1,2\n  < abc123\n  < def456\n  ---\n  > abc101\n  > def111\nfile2 from dir2: \n  1,2c1,2\n  < abc123\n  < def456\n  ---\n  > abc101\n  > def111\nfile1 from dir1: \n  1,2c1,2\n  < 123abc\n  < 456def\n  ---\n  > 101abc\n  > 111def\nfile1 from dir2: \n  1,2c1,2\n  < 123abc\n  < 456def\n  ---\n  > 101abc\n  > 111def\n"
}
diff
  • 1 1 个回答
  • 29 Views

1 个回答

  • Voted
  1. Best Answer
    Vladimir Botka
    2023-05-08T19:00:42+08:002023-05-08T19:00:42+08:00

    例如,给定文件

    shell> ssh admin@test_11 ls -1 /tmp/dir[1,2]
    /tmp/dir1:
    file1
    file2
    
    /tmp/dir2:
    file1
    file2
    
    shell> ssh admin@test_13 ls -1 /tmp/dir[1,2]
    /tmp/dir1:
    
    /tmp/dir2:
    

    和差异

    shell> ssh admin@test_11 diff /tmp/dir1/file1 /tmp/dir2/file1
    31,32d30
    < User1:*:1002:1004:My User1:/home/User1:/bin/sh
    < MyUser1:*:1003:1005:My User1:/home/MyUser1:/bin/sh
    
    shell> ssh admin@test_11 diff /tmp/dir1/file2 /tmp/dir2/file2
    33,34d32
    < alice:*:1004:1006:Alice:/home/alice:/bin/sh
    < bob:*:1005:1007:Bob:/home/bob:/bin/sh
    
    

    声明变量

      dir1: /tmp/dir1
      dir2: /tmp/dir2
      dir1_files: "{{ out_dir1.files|map(attribute='path') }}"
      dir2_files: "{{ out_dir2.files|map(attribute='path') }}"
    

    并找到文件

        - find:
            paths: "{{ dir1 }}"
            file_type: file
          register: out_dir1
        - find:
            paths: "{{ dir2 }}"
            file_type: file
          register: out_dir2
    

    找到共享文件。声明变量

      files_common: "{{ dir1_files|map('basename')|
                        intersect(dir2_files|map('basename')) }}"
    

    分别为 test_11 和 test_13 给出(删节)

      files_common:
      - file1
      - file2
    
      files_common: []
    

    比较共享文件。您必须忽略这些错误,因为如果文件不同,diff将返回rc=1

      - command: "diff {{ dir1 }}/{{ item }} {{ dir2 }}/{{ item }}"
        loop: "{{ files_common }}"
        ignore_errors: true
        register: out_diff
    

    并创建报告

        - debug:
            msg: |
              {% for i in out_diff.results %}
              {{ i.cmd|join(' ') }}: |
                {{ i.stdout|indent(2) }}
              {% endfor %}
    

    分别为 test_11 和 test_13 给出(删节)

      msg: |-
        diff /tmp/dir1/file1 /tmp/dir2/file1: |
          31,32d30
          < User1:*:1002:1004:My User1:/home/User1:/bin/sh
          < MyUser1:*:1003:1005:My User1:/home/MyUser1:/bin/sh
        diff /tmp/dir1/file2 /tmp/dir2/file2: |
          33,34d32
          < alice:*:1004:1006:Alice:/home/alice:/bin/sh
          < bob:*:1005:1007:Bob:/home/bob:/bin/sh
    
      msg: ""
    

    用于测试的完整剧本示例

    - hosts: all
    
      vars:
    
        dir1: /tmp/dir1
        dir2: /tmp/dir2
        dir1_files: "{{ out_dir1.files|map(attribute='path') }}"
        dir2_files: "{{ out_dir2.files|map(attribute='path') }}"
        files_common: "{{ dir1_files|map('basename')|
                          intersect(dir2_files|map('basename')) }}"
        
        
      tasks:
    
        - find:
            paths: "{{ dir1 }}"
            file_type: file
          register: out_dir1
        - find:
            paths: "{{ dir2 }}"
            file_type: file
          register: out_dir2
        - debug:
            var: files_common
    
        - command: "diff {{ dir1 }}/{{ item }} {{ dir2 }}/{{ item }}"
          loop: "{{ files_common }}"
          ignore_errors: true
          register: out_diff
        - debug:
            msg: |
              {% for i in out_diff.results %}
              {{ i.cmd|join(' ') }}: |
                {{ i.stdout|indent(2) }}
              {% endfor %}
    

    问:“我不喜欢 msg 模块输出,我更喜欢输出部分中类似于 Q 中给出的格式,它可以实现吗?”

    答:当然。试试下面的模板。如果这不是您喜欢的,请编辑您的问题并提供您更喜欢的示例

        - debug:
            msg: |
              {% for i in out_diff.results %}
              {{ i.cmd.1|basename }} from {{ i.cmd.1|dirname }}: 
                {{ i.stdout|indent(2) }}
              {{ i.cmd.2|basename }} from {{ i.cmd.2|dirname }}: 
                {{ i.stdout|indent(2) }}
              {% endfor %}
    

    输出的格式取决于回调。请参阅DEFAULT_STDOUT_CALLBACK。如果你使用ansible.builtin.default回调设置 ANSIBLE_CALLBACK_RESULT_FORMAT=yaml

    shell> ANSIBLE_STDOUT_CALLBACK=default ANSIBLE_CALLBACK_RESULT_FORMAT=yaml ansible-playbook pb.yml
    
      ...
    ok: [test_11] => 
        msg: |-
            file1 from /tmp/dir1:
              31,32d30
              < User1:*:1002:1004:My User1:/home/User1:/bin/sh
              < MyUser1:*:1003:1005:My User1:/home/MyUser1:/bin/sh
            file1 from /tmp/dir2:
              31,32d30
              < User1:*:1002:1004:My User1:/home/User1:/bin/sh
              < MyUser1:*:1003:1005:My User1:/home/MyUser1:/bin/sh
            file2 from /tmp/dir1:
              33,34d32
              < alice:*:1004:1006:Alice:/home/alice:/bin/sh
              < bob:*:1005:1007:Bob:/home/bob:/bin/sh
            file2 from /tmp/dir2:
              33,34d32
              < alice:*:1004:1006:Alice:/home/alice:/bin/sh
              < bob:*:1005:1007:Bob:/home/bob:/bin/sh
    ok: [test_13] => 
        msg: ""
    

    看

    shell> ansible-doc -t callback ansible.builtin.default
    
    • 2

相关问题

  • 两个目录的差异文件名?

  • 将 diff -e 的输出与 sed 一起使用

  • 仅显示未注释行的配置文件的差异

  • 确定两个 iso 图像是否相等

  • git:仅在 GUI 中使用视觉差异(融合)

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve