Vous devez essentiellement comparer deux fichiers, en ignorant conditionnellement l'octet de fin. Il n'y a pas d'option 'diff' pour faire cela - mais il y a un certain nombre de façons de le faire (par exemple, la différence hexadécimale vient également à l'esprit.)
Pour utiliser 'diff', vous devez fondamentalement modifier les fichiers auxquels il manque la nouvelle ligne à la fin d'un fichier, puis comparer. Vous pouvez créer un répertoire temporaire avec les fichiers modifiés, ou avec un peu de script, cela pourrait être fait en mémoire. (La préférence dépend de la préférence, de la taille du fichier, du nombre de fichiers ...)
Par exemple, ce qui suit modifiera le contenu d'un fichier (utilisez sed -i
pour modifier sur place, cela s'imprime simplement sur stdout) pour ajouter une nouvelle ligne s'il en manque une (ou laisser le fichier inchangé s'il y a déjà une nouvelle ligne):
sed -e '$a\' file1.txt
Et juste pour revoir la syntaxe 'diff' (renvoyer true signifie qu'ils sont identiques, false signifie différent):
$ diff a/file1.txt b/file1.txt \
&& echo '** are same' || echo '** are different'
2c2
< eof
---
> eof
\ No newline at end of file
** are different
Vérifiez que seul l'espace blanc est différent:
$ diff --ignore-all-space a/file1.txt b/file1.txt \
&& echo '** are same' || echo '** are different'
** are same
En bash, nous pouvons utiliser 'sed' pour manipuler le contenu du fichier lorsqu'il est passé à 'diff' (les fichiers d'origine restent inchangés):
$ diff <(sed -e '$a\' a/file1.txt) <(sed -e '$a\' b/file1.txt) \
&& echo '** are same' || echo '** are different'
** are same
Il ne vous reste plus qu'à émuler diff -r
pour comparer récursivement les répertoires. Si vous comparez les répertoires a
et b
, alors pour tous les fichiers dans a
(par exemple, a/dir1/dir2/file.txt
) dérivez le chemin vers le fichier dans b
(par exemple, b/dir1/dir2/file.txt
) et comparez:
$ for f in $( find a -type f )
> do
> diff <(sed -e '$a\' $f) <(sed -e '$a\' b/${f#*/})
> done
Une version un peu plus verbeuse:
$ for f in $( find a -type f )
> do
> f1=$f
> f2=b/${f#*/}
> echo "compare: $f1 $f2"
> diff <(sed -e '$a\' $f1) <(sed -e '$a\' $f2) \
> && echo '** are same' || echo '** are different'
> done && echo '** all are same' || echo '** all are different'
compare: a/file1.txt b/file1.txt
** are same
compare: a/file2.txt b/file2.txt
** are same
** all are same
sed -e '$a\'
que fait exactement? thxsed
, étant donné le-e
script / expression ( ) suivant , qui correspond à la fin du fichier ($
), et effectuer l'action "ajouter" (a \), mais ne spécifiez en fait aucun texte (rien après le `\`) qui va toujours ajouter un EOF / newline à la fin du fichier (seulement s'il est manquant).a\
encore vu .J'ai résolu le problème en ajoutant une nouvelle ligne à chacun des fichiers et en ignorant les lignes vides dans le diff (option
-B
). Ces solutions peuvent ne pas convenir à votre cas d'utilisation, mais elles peuvent aider les autres:la source
Dirigez la sortie de
diff
vers unegrep
commande qui supprime le message que vous ne souhaitez pas voir.la source
J'ai juste pensé à une approche différente, aussi, qui fonctionnera pour des fichiers plus volumineux (et ne copie toujours pas ou ne modifie pas les fichiers originaux). Vous devrez toujours émuler la traversée récursive du répertoire (et il existe plusieurs façons de le faire), mais cet exemple n'utilise pas 'sed', mais compare simplement deux fichiers, à l'exclusion du dernier octet, en utilisant
cmp
, par exemple,Faites toujours une boucle sur tous les fichiers du répertoire et pour deux fichiers a / file.txt et b / file.txt, calculez la plus grande taille de fichier et soustrayez-en un, puis faites un diff binaire (
cmp
) en utilisant ce nombre d'octets (également dans frapper):La boucle sur les fichiers serait la même que dans l'autre réponse en utilisant
sed
etdiff
.la source
La réponse est simple.
Le message concernant la nouvelle ligne manquante ne se trouve pas dans le flux de sortie de
diff
mais dans le flux d'erreur. Alors pliez-le au nirvana et vous avez terminé pour de bonla source
Il y a un drapeau dans diff commnad:
--strip-trailing-cr
qui fait exactement ce que vous avez demandéla source
/r/n
comme/n
et n'a rien à voir avec un supplément/n
juste avant l'EOF.