Jak porównać dwa pliki ze skryptem powłoki?

10

Biorąc pod uwagę dwa pliki, chcę napisać skrypt powłoki, który odczytuje każdy wiersz z pliku 1 i sprawdza, czy jest on w pliku 2. Jeśli wiersz nie zostanie znaleziony, powinien wypisać dwa pliki są różne i wyjść. Pliki mogą zawierać słowa liczb lub cokolwiek innego. Na przykład :

plik1:

Hi!
1234
5678
1111
hello

plik2:

1111
5678
1234
Hi!
hello

W takim przypadku dwa pliki powinny być równe. jeśli plik2 ma „cześć !!!” zamiast „cześć”, pliki są inne. Używam skryptu bash. W jaki sposób mogę to zrobić. Nie jest ważne, że muszę to robić w zagnieżdżonej pętli, ale tak myślałem, że to jedyny sposób. Dzięki za pomoc.

0x0
źródło

Odpowiedzi:

9

W bash:

diff --brief <(sort file1) <(sort file2)
Ignacio Vazquez-Abrams
źródło
Co jeśli plik jest plikiem csv. czy sortowanie nadal działałoby?
0x0
sortnie dba o dokładną treść, chyba że tak mówisz.
Ignacio Vazquez-Abrams
Czy można znaleźć, które linie różnią się?
0x0
Usuń --briefi dodaj opcje formatu, np -u.
Ignacio Vazquez-Abrams
10

diffustawia status wyjścia, aby wskazać, czy pliki są takie same, czy nie. Status wyjścia jest dostępny w specjalnej zmiennej $?. Możesz rozwinąć odpowiedź Ignacio w ten sposób:

diff --brief <(sort file1) <(sort file2) >/dev/null
comp_value=$?

if [ $comp_value -eq 1 ]
then
    echo "do something because they're different"
else
    echo "do something because they're identical"
fi
Doug Harris
źródło
3
Możesz po prostu obejść się if diff ... >/dev/nullbez nawiasów i zmiennej.
Wstrzymano do odwołania.
1

Dodając to, ponieważ myślę, że [[]] && || konstrukcja jest dość schludna:

#!/bin/bash

[[ `diff ${HOME}/file1 ${HOME}/file2` ]] &&  
   (echo "files different") ||
   (echo "files same")
mmrtnt
źródło
1

Powinien również działać:

comm -3 file1 file2

Myślę, że to wystarczająca liczba postaci do odpowiedzi ...

mpez0
źródło
1

Chociaż diffjest to bardzo dobra odpowiedź, prawdopodobnie użyłbym cmpzamiast tego, który jest specjalnie do porównania bajt po bajcie dwóch plików.

https://linux.die.net/man/1/cmp

Z tego powodu ma dodatkową zaletę polegającą na porównywaniu plików binarnych.

if cmp -s "file1" "file2"
then
   echo "The files match"
else
   echo "The files are different"
fi

Jestem przekonany, że jest szybszy niż używanie, diffchociaż osobiście tego nie testowałem.

Richard
źródło
Czy przypadek „pliki są inne” nie byłby pierwszy? Test if pyta, czy coś jest prawdą, tj. Niezerowy kod powrotu. Jeśli pliki się zgadzają, cmp zwraca 0 (na stronę podręcznika), więc powinien to być drugi przypadek.
user8162,
@ user8162 To, co mówisz, ma sens, jednak właśnie to przetestowałem i jest to właściwa metoda. Nie jestem pewien, dlaczego tak jest w istocie.
Richard