防止 diff 检查文件末尾的换行符

防止 diff 检查文件末尾的换行符

我有两棵大树,我想比较它们。树中的一些文件不同,只是因为一个文件末尾有换行符,而另一个文件缺少这个换行符。我想忽略这个事实。我试过diff这样调用:

diff --ignore-all-space -r <dir1> <dir2>

这是可行的。我的问题是它还忽略了其他可能很重要的差异(与空间相关)。

总结一下:我只是想要忽略 EOF 处的换行符。使用 可以实现吗diff

答案1

您基本上需要比较两个文件,有条件地忽略尾随字节。没有“diff”选项可以执行此操作 - 但有很多方法可以做到这一点(例如,十六进制 diff 也浮现在脑海中。)

要使用“diff”,您基本上必须修改文件末尾缺少换行符的文件,然后进行比较。您可以创建一个包含修改后文件的临时目录,或者使用一些脚本在内存中完成。(至于首选哪种方法取决于偏好、文件大小、文件数量……)

例如,下面将修改文件的内容(用于sed -i就地修改,这只会打印到标准输出)以在缺少换行符时添加换行符(如果已经有换行符,则保持不变):

sed -e '$a\'  file1.txt

回顾一下“diff”语法(返回 true 表示它们相同,返回 false 表示不同):

$ diff a/file1.txt   b/file1.txt  \
      && echo '** are same' || echo '** are different'
2c2
< eof
---
> eof
\ No newline at end of file
** are different

验证只有空格不同:

$ diff --ignore-all-space  a/file1.txt   b/file1.txt \
     && echo '** are same' || echo '** are different'
** are same

在 bash 中,我们可以使用“sed”来操作文件内容,因为它被传递给“diff”(原始文件保持不变):

$ diff <(sed -e '$a\' a/file1.txt) <(sed -e '$a\' b/file1.txt) \
     && echo '** are same' || echo '** are different'
** are same

现在您要做的就是diff -r模拟递归比较目录。如果比较目录ab,则对于a(例如)中的所有文件,导出(例如)a/dir1/dir2/file.txt中的文件路径并进行比较:bb/dir1/dir2/file.txt

$ for f in $( find a -type f  )
> do
>    diff <(sed -e '$a\' $f) <(sed -e '$a\' b/${f#*/})
> done

稍微详细一点的版本:

$ 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

答案2

我通过在每个文件中添加换行符并忽略 diff 中的空行(选项-B)解决了该问题。此解决方案可能不适合你的用例,但可能对其他人有所帮助:

echo >> $FILE1 
echo >> $FILE2
diff -B $FILE1 FILE2 

答案3

在 Google 上搜索时,一个旧帖子竟然出现在搜索结果的首位,这很不寻常suppress no newline at end of file while diff。更令人惊讶的是,在浏览完所有回复后,似乎 11 年来这个问题都没有明确的答案!

因此,我决定尝试不同的方法并运行命令diff --help|grep trail。它显示

-Z, --ignore-trailing-space     ignore white space at line end

它有效,而且我猜,当比较位于多个嵌套目录中的代码批次时,这可能会很有帮助。

答案4

我也想到了一种不同的方法,它适用于较大的文件(并且仍然不会复制或修改原始文件)。您仍然必须模拟递归目录遍历(并且有很多方法可以做到这一点),但此示例不使用“sed”,而是仅比较两个文件(不包括最后一个字节),例如cmp

$ cmp  a/file1.txt  b/file1.txt  && echo '** are same' || echo '** are different'
cmp: EOF on b/file1.txt
** are different

$ du -b a/file1.txt  b/file1.txt 
13  a/file1.txt
12  b/file1.txt

$ cmp  -n 12 a/file1.txt  b/file1.txt  && echo '** are same' || echo '** are different'
** are same

仍然循环遍历目录中的所有文件,对于两个文件 a/file.txt 和 b/file.txt,计算较大的文件大小并减一,然后cmp使用这个字节数执行二进制差异()(也在 bash 中):

(( bytes = $(du -b a/file.txt  b/file.txt  | sort -nr | head -1  | cut -f1) - 1 ))
cmp -n $bytes a/file.txt b/file.txt

sed循环遍历文件与使用和 的其他答案相同diff

相关内容