简体   繁体   中英

How to compare multiple files in Ansible

I am trying to find a way to compare multiple files in a directory to files in another directory. For example - there are 10 files in a directory /home/ansible/properties/ and similar set of files in another directory on remote host like /opt/apps/properties/. I want to compare each of them probably using checksum and even if one of the file is changed then do some task -

Below of my play can compare one file but is there a way to compare all the files or for that matter a directory?

- name: Get checksum of my First file
  stat:
    path : "/home/ansible/properties/my.properties"
  register: myfirstfile

- name: Current SHA1
  set_fact:
    1stFilechecksum: "{{ myfirstfile.stat.checksum }}"

- name: Get checksum of my Second File
  stat:
    path : "/opt/aaps/properties/my.properties"
  register: mysecondfile

- name: Current SHA1
  set_fact:
    2ndFilechecksum: "{{ mysecondfile.stat.checksum }}"

- name: Comparing 2 files
  debug:
    msg: "Do Something....."
  when:  1stFilechecksum != 2ndFilechecksum

Test file tree according to your description

... or at least what I understood from it.

/tmp/test/a          /tmp/test/b
├── file10.txt       ├── file10.txt
├── file1.txt        ├── file1.txt
├── file2.txt        ├── file2.txt
├── file3.txt        ├── file3.txt
├── file4.txt        ├── file4.txt
├── file5.txt        ├── file5.txt
├── file6.txt        ├── file6.txt
├── file7.txt        ├── file7.txt
├── file8.txt        ├── file8.txt
├── file9.txt        ├── file9.txt
└── toto.txt         └── titi.txt

As you can see all files are common except on file in each dir. Those will be be excluded from comparison. For the common files all are different except file2.txt and file5.txt having the same content.

The bases used for the solution

  • We search for all files in both directories in a loop with find . All files in a are in results[0] , those from b in results[1] . The get_checksum option gathers the info we need.
  • In the next task:
    • We loop on files found in a .
    • On each iteration, we calculate the corresponding file in b by selecting with selectattr only the list elements having the same path name after replacing the dir path. Keeping the first element of the result gives our file. In case the result is empty (not a file in common), we default to an empty object
    • The when clause checks that the files exist (common else we skip) and that they are different (checksum is not equal)
    • loop_control is used to customize the loop varialbe name for readability (ie item => file1) and to limit the output of the loop item to something understandable.

The playbook

---
- name: compare files in two dirs
  hosts: localhost
  gather_facts: false

  vars:
    dir1: /tmp/test/a
    dir2: /tmp/test/b

  tasks:

    - name: "Find all files in {{ dir1 }} and {{ dir2 }}"
      find:
        paths:
          - "{{ item }}"
        get_checksum: true
      register: search_files
      loop:
        - "{{ dir1 }}"
        - "{{ dir2 }}"


    - name: "Compare checksums from {{ dir1 }} to {{ dir2 }}. do something if different"
      vars:
        file2: >-
          {{
            search_files.results[1].files |
            selectattr('path', 'eq', file1.path | replace(dir1, dir2)) |
            list |
            first |
            default({})
          }}
      debug:
        msg: "Files differ. Do something"
      loop: "{{ search_files.results[0].files }}"
      loop_control:
        loop_var: file1
        label: "Comparing {{ file1.path }} to {{ file2.path | default('N/A') }}"
      when:
        - file2.path is defined
        - file1.checksum != file2.checksum

The result

$ ansible-playbook test.yml 

PLAY [compare files in two dirs] ***************************************************************************************************************

TASK [Find all files in /tmp/test/a and /tmp/test/b] *******************************************************************************************
ok: [localhost] => (item=/tmp/test/a)
ok: [localhost] => (item=/tmp/test/b)

TASK [Compare checksums from /tmp/test/a to /tmp/test/b. do something if different] ************************************************************
ok: [localhost] => (item=Comparing /tmp/test/a/file1.txt to /tmp/test/b/file1.txt) => {
    "msg": "Files differ. Do something"
}
skipping: [localhost] => (item=Comparing /tmp/test/a/file2.txt to /tmp/test/b/file2.txt) 
ok: [localhost] => (item=Comparing /tmp/test/a/file3.txt to /tmp/test/b/file3.txt) => {
    "msg": "Files differ. Do something"
}
ok: [localhost] => (item=Comparing /tmp/test/a/file4.txt to /tmp/test/b/file4.txt) => {
    "msg": "Files differ. Do something"
}
skipping: [localhost] => (item=Comparing /tmp/test/a/file5.txt to /tmp/test/b/file5.txt) 
ok: [localhost] => (item=Comparing /tmp/test/a/file6.txt to /tmp/test/b/file6.txt) => {
    "msg": "Files differ. Do something"
}
ok: [localhost] => (item=Comparing /tmp/test/a/file7.txt to /tmp/test/b/file7.txt) => {
    "msg": "Files differ. Do something"
}
ok: [localhost] => (item=Comparing /tmp/test/a/file8.txt to /tmp/test/b/file8.txt) => {
    "msg": "Files differ. Do something"
}
ok: [localhost] => (item=Comparing /tmp/test/a/file9.txt to /tmp/test/b/file9.txt) => {
    "msg": "Files differ. Do something"
}
ok: [localhost] => (item=Comparing /tmp/test/a/file10.txt to /tmp/test/b/file10.txt) => {
    "msg": "Files differ. Do something"
}
skipping: [localhost] => (item=Comparing /tmp/test/a/toto.txt to N/A) 

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM