Je veux comparer file1 avec file2 et générer un fichier3 qui contient les lignes dans file1 qui ne sont pas présentes dans file2.
Je veux comparer file1 avec file2 et générer un fichier3 qui contient les lignes dans file1 qui ne sont pas présentes dans file2.
Réponses:
diff (1) n'est pas la réponse, mais comm (1) l'est.
NAME
comm - compare two sorted files line by line
SYNOPSIS
comm [OPTION]... FILE1 FILE2
...
-1 suppress lines unique to FILE1
-2 suppress lines unique to FILE2
-3 suppress lines that appear in both files
Alors
comm -2 -3 file1 file2 > file3
Les fichiers d'entrée doivent être triés. Si ce n'est pas le cas, triez-les d'abord. Cela peut être fait avec un fichier temporaire, ou ...
comm -2 -3 <(sort file1) <(sort file2) > file3
à condition que votre shell supporte la substitution de processus (bash le fait).
comm -23
L'utilitaire Unix diff
est conçu exactement dans ce but.
$ diff -u file1 file2 > file3
Consultez le manuel et Internet pour les options, les différents formats de sortie, etc.
Considérez ceci:
fichier a.txt:
abcd
efgh
fichier b.txt:
abcd
Vous pouvez trouver la différence avec:
diff -a --suppress-common-lines -y a.txt b.txt
La sortie sera:
efgh
Vous pouvez rediriger la sortie dans un fichier de sortie (c.txt) en utilisant:
diff -a --suppress-common-lines -y a.txt b.txt > c.txt
Cela répondra à votre question:
"... qui contient les lignes du fichier1 qui ne sont pas présentes dans le fichier2."
-d
, ce qui fera de diff
son mieux pour trouver le plus petit diff. -i
, -E
, -w
, -B
Et --suppress-blank-empty
peut aussi être utile de temps en temps, mais pas toujours. Si vous ne savez pas ce qui correspond à votre cas d'utilisation, essayez d' diff --help
abord (ce qui est généralement une bonne idée lorsque vous ne savez pas ce qu'une commande peut faire).
Parfois, diff
c'est l'utilitaire dont vous avez besoin, mais parfois join
plus approprié. Les fichiers doivent être pré-triés ou, si vous utilisez un shell prenant en charge la substitution de processus comme bash, ksh ou zsh, vous pouvez effectuer le tri à la volée.
join -v 1 <(sort file1) <(sort file2)
Essayer
sdiff file1 file2
Cela fonctionne généralement beaucoup mieux dans la plupart des cas pour moi. Vous voudrez peut-être trier les fichiers avant, si l'ordre des lignes n'est pas important (par exemple, certains fichiers de configuration de texte).
Par exemple,
sdiff -w 185 file1.cfg file2.cfg
sdiff <(sort file1) <(sort file2)
)
Si vous avez besoin de résoudre cela avec coreutils, la réponse acceptée est bonne:
comm -23 <(sort file1) <(sort file2) > file3
Vous pouvez également utiliser sd (stream diff), qui ne nécessite pas de tri ni de substitution de processus et prend en charge des flux infinis, comme ceci:
cat file1 | sd 'cat file2' > file3
Probablement pas tellement d'un avantage sur cet exemple, mais considérez-le toujours; dans certains cas, vous ne pourrez pas utiliser comm
ni grep -F
ni diff
.
Voici un article de blog que j'ai écrit sur les différents flux sur le terminal, qui présente sd.
Beaucoup de réponses déjà, mais aucune d'entre elles n'est parfaite à mon humble avis. La réponse de Thanatos laisse quelques caractères supplémentaires par ligne et la réponse de Sorpigal nécessite que les fichiers soient triés ou pré-triés, ce qui peut ne pas être adéquat dans toutes les circonstances.
Je pense que la meilleure façon d'obtenir les lignes qui sont différentes et rien d' autre (pas de caractères supplémentaires, pas de re-commande) est une combinaison de diff
, grep
et awk
(ou similaire).
Si les lignes ne contiennent aucun "<", une courte ligne unique peut être:
diff urls.txt* | grep "<" | sed 's/< //g'
mais cela supprimera toutes les instances de "<" (moins de, espace) des lignes, ce qui n'est pas toujours OK (par exemple le code source). L'option la plus sûre est d'utiliser awk:
diff urls.txt* | grep "<" | awk '{for (i=2; i<NF; i++) printf $i " "; print $NF}'
Cette ligne diffère les deux fichiers, puis filtre la sortie de style ed de diff, puis supprime le "<" de fin ajouté par diff. Cela fonctionne même si les lignes contiennent elles-mêmes des "<".
diff a1.txt a2.txt | grep '> ' | sed 's/> //' > a3.txt
J'ai essayé presque toutes les réponses de ce fil, mais aucune n'était complète. Après quelques sentiers au-dessus, un a fonctionné pour moi. diff vous donnera une différence mais avec quelques charas spéciaux indésirables. où vos lignes de différence réelles commencent par «>». donc l'étape suivante consiste à grep les lignes commençant par '>' et suivies de la suppression de la même chose avec sed .
<
. Vous verrez cela si vous permutez l'ordre des fichiers d'entrée. Même si vous faisiez cela, vous voudriez omettre grep
en utilisant plus de sed: `diff a1 a2 | sed '/> / s ///' 'Cela peut encore casser des lignes contenant >
ou <
dans la bonne situation et laisse toujours des lignes supplémentaires décrivant les numéros de ligne. Si vous voulez essayer cette approche une meilleure façon serait la suivante: diff -C0 a1 a2 | sed -ne '/^[+-] /s/^..//p'
.
Vous pouvez utiliser diff
avec le formatage de sortie suivant:
diff --old-line-format='' --unchanged-line-format='' file1 file2
--old-line-format=''
, désactiver la sortie pour fichier1 si la ligne était différente de la comparaison dans fichier2.
--unchanged-line-format=''
, désactivez la sortie si les lignes étaient identiques.