Comment puis-je faire en sorte que diff affiche uniquement les lignes ajoutées et supprimées? Si diff ne peut pas le faire, quel outil peut-il faire?
Une autre façon de voir les choses:
Afficher les lignes qui n'existent que dans le fichier a: (c'est-à-dire ce qui a été supprimé de a)
comm -23 a b
Afficher les lignes qui n'existent que dans le fichier b: (c'est-à-dire ce qui a été ajouté à b)
comm -13 a b
Afficher les lignes qui n'existent que dans un fichier ou dans l'autre: (mais pas les deux)
comm -3 a b | sed 's/^\t//'
(Avertissement: si le fichier a
contient des lignes commençant par TAB, il (le premier TAB) sera supprimé de la sortie.)
REMARQUE: Les deux fichiers doivent être triés pour que comm
fonctionne correctement. S'ils ne sont pas déjà triés, vous devez les trier:
sort <a >a.sorted
sort <b >b.sorted
comm -12 a.sorted b.sorted
Si les fichiers sont extrêmement longs, cela peut être assez lourd car cela nécessite une copie supplémentaire et donc deux fois plus d'espace disque.
comm
pourrait faire ce que vous voulez. Depuis sa page de manuel:
LA DESCRIPTION
Comparez les fichiers triés FILE1 et FILE2 ligne par ligne.
Sans aucune option, produisez une sortie à trois colonnes. La première colonne contient des lignes propres à FILE1, la deuxième colonne contient des lignes uniques à FILE2 et la troisième colonne contient des lignes communes aux deux fichiers.
Ces colonnes sont supprimables avec -1
, -2
et -3
respectivement.
Exemple:
[root@dev ~]# cat a
common
shared
unique
[root@dev ~]# cat b
common
individual
shared
[root@dev ~]# comm -3 a b
individual
unique
Et si vous voulez juste les lignes uniques et ne vous souciez pas du fichier dans lequel elles se trouvent:
[root@dev ~]# comm -3 a b | sed 's/^\t//'
individual
unique
Comme le dit la page de manuel, les fichiers doivent être triés au préalable.
Pour afficher les ajouts et les suppressions sans contexte, les numéros de ligne, +, -, <,>! etc, vous pouvez utiliser diff comme ceci:
diff --changed-group-format='%<%>' --unchanged-group-format='' a.txt b.txt
Par exemple, compte tenu de deux fichiers:
a.txt
Common
Common
A-ONLY
Common
b.txt
Common
B-ONLY
Common
Common
La commande suivante affichera les lignes supprimées de a ou ajoutées à b:
diff --changed-group-format='%<%>' --unchanged-group-format='' a.txt b.txt
production:
B-ONLY
A-ONLY
Cette commande légèrement différente affichera les lignes supprimées de a.txt:
diff --changed-group-format='%<' --unchanged-group-format='' a.txt b.txt
production:
A-ONLY
Enfin, cette commande affichera les lignes ajoutées à a.txt
diff --changed-group-format='%>' --unchanged-group-format='' a.txt b.txt
production
B-ONLY
C'est ce que diff fait par défaut ... Peut-être que vous devez ajouter des drapeaux pour ignorer les espaces?
diff -b -B
doit ignorer les lignes vides et les différents nombres d'espaces.
Non, diff
ne montre pas réellement les différences entre deux fichiers dans la façon dont on pourrait le penser. Il produit une séquence de commandes d'édition pour un outil comme patch
à utiliser pour changer un fichier en un autre.
La difficulté pour toute tentative de faire ce que vous cherchez est de définir ce qui constitue une ligne qui a changé par rapport à une ligne supprimée suivie d'une ligne ajoutée. Que faire également lorsque des lignes sont ajoutées, supprimées et modifiées les unes à côté des autres.
Les outils de comparaison visuelle assemblent deux fichiers afin qu'un segment avec le même nombre de lignes mais un contenu différent soit considéré comme un segment modifié. De nouvelles lignes entre les segments correspondants sont considérées comme des segments ajoutés.
C'est également ainsi que fonctionne l'outil de ligne de commande sdiff, qui montre une comparaison côte à côte de deux fichiers dans un terminal. Les lignes modifiées sont séparées par | personnage. Si une ligne n'existe que dans le fichier A, <est utilisé comme caractère de séparation. Si une ligne n'existe que dans le fichier B,> est utilisé comme séparateur. Si vous n'avez pas de caractères <et> dans les fichiers, vous pouvez l'utiliser pour afficher uniquement les lignes ajoutées:
sdiff A B | grep '[<>]'
Merci senarvi, votre solution (non votée) m'a en fait donné exactement ce que je voulais après avoir recherché les âges sur une tonne de pages.
En utilisant votre réponse, voici ce que j'ai trouvé pour obtenir la liste des choses modifiées/ajoutées/supprimées. L'exemple utilise 2 versions du fichier/etc/passwd et imprime le nom d'utilisateur pour les enregistrements appropriés.
#!/bin/bash
sdiff passwd1 passwd2 | grep '[|]' | awk -F: '{print "changed: " $1}'
sdiff passwd1 passwd2 | grep '[<]' | awk -F: '{print "deleted: " $1}'
sdiff passwd1 passwd2 | grep '[>]' | awk -F\> '{print $2}' | awk -F: '{print "added: " $1}'
Je trouve cette forme particulière souvent utile:
diff --changed-group-format='-%<+%>' --unchanged-group-format='' f g
Exemple:
printf 'a\nb\nc\nd\ne\nf\ng\n' > f
printf 'a\nB\nC\nd\nE\nF\ng\n' > g
diff --old-line-format=$'-%l\n' \
--new-line-format=$'+%l\n' \
--unchanged-line-format='' \
f g
Production:
-b
-c
+B
+C
-e
-f
+E
+F
Il montre donc les anciennes lignes avec -
suivi immédiatement de la nouvelle ligne correspondante avec +
.
Si nous avions une suppression de C
:
printf 'a\nb\nd\ne\nf\ng\n' > f
printf 'a\nB\nC\nd\nE\nF\ng\n' > g
diff --old-line-format=$'-%l\n' \
--new-line-format=$'+%l\n' \
--unchanged-line-format='' \
f g
cela ressemble à ceci:
-b
+B
+C
-e
-f
+E
+F
Le format est documenté à man diff
:
--line-format=LFMT
format all input lines with LFMT`
et:
LTYPE is 'old', 'new', or 'unchanged'.
GTYPE is LTYPE or 'changed'.
et:
LFMT (only) may contain:
%L contents of line
%l contents of line, excluding any trailing newline
[...]
Question connexe: https://stackoverflow.com/questions/15384818/how-to-get-the-difference-only-additions-between-two-files-in-linux
Testé dans Ubuntu 18.04.