2010-07-16 259 views
9

我有大量的源文件,最后都没有换行符。如何解决大量文件的“文件末尾没有换行符”警告?

如何自动添加换行符到每个换行符的结尾?

有些可能已经有换行符,所以只能在必要时添加。

我可能不是在寻找代码本身,而只是在终端中运行以添加必要的换行符(或某种编程或开发工具)。

回答

3

为了方便起见,将诺曼的答案转换为分离式单行程。

for i in * ; do echo $i; \ 
if diff /dev/null "$i" | tail -1 | \ 
    grep '^\\ No newline' > /dev/null; then echo >> "$i"; \ 
fi; done 

替换*与任何你想要的文件模式,例如*.c

,另一个只是告诉你哪些文件被破坏:

for i in * ; do \ 
if diff /dev/null "$i" | tail -1 | \ 
    grep '^\\ No newline' > /dev/null; then echo $i; \ 
fi; done 
+0

这些解决方案都不适用于我 – 2012-11-10 10:09:58

+1

如果您希望它以递归方式进行交换,可以交换'*'用'$(find。-type f)'或'$(找到 -type f -name )' – durron597 2013-08-30 14:53:40

7

如果你有机会获得Unix工具,你可以运行diff找出哪些文件缺乏一个换行符,然后将其追加:

#!/bin/sh 
for i 
do 
    if diff /dev/null "$i" | tail -1 | grep '^\\ No newline' > /dev/null 
    then 
    echo >> "$i" 
    fi 
done 

我靠diff生产具有在\消息第一列tail给我最后一行diff的输出,并且grep告诉我最后一行是否是我正在查找的消息。如果一切正常,则echo会生成一个换行符,>>会将其附加到文件"$i"。如果文件名中有空格,"$i"左右的引号可以确保事情仍然有效。

+2

不错,但是grep会返回一个本地化的消息,比如“\ Brak znaku nowej linii(etc.)”。另外,diff输出整个文件。我会使用'tail -1 $ f | grep'\ n''的条件(在我的盒子上工作)。 – 2012-12-12 12:46:59

+0

@TomaszGandor:'tail -1 filename | grep'\ n'似乎总是在我的mac上返回一个错误的结果,不管是否有尾随的换行符。 – Gino 2017-05-27 14:03:39

2

OK,在评论抱怨后,有我更好的解决方案 首先,你要知道,这些文件丢失换行符:

find -type f -exec sh -c "tail -1 {} | xxd -p | tail -1 | grep -v 0a$" ';' -print 

不超快速(要求每个文件一对夫妇的进程),但它的实际用途确定。

现在,当你拥有了它,你不妨加入新行,与其他-exec

find -type f -exec sh -c "tail -1 {} | xxd -p | tail -1 | grep -v 0a$" ';' -exec sh -c "echo >> {}" ';' 

可能的陷阱:

  • 如果文件名是不好的,例如他们有空间,您可能需要tail -1 \"{}\"。 或确实找对了吗?

  • 您可能想要添加更多的过滤来查找,如-name \*py等。

  • 想想可能的DOS/Unix换行在使用之前乱七八糟(首先修复)。

编辑:

如果你不喜欢这些命令的输出(呼应一些十六进制),加-q到grep:

find -type f -exec sh -c "tail -1 {} | xxd -p | tail -1 | grep -q -v 0a$" ';' -print 
find -type f -exec sh -c "tail -1 {} | xxd -p | tail -1 | grep -q -v 0a$" ';' -exec sh -c "echo >> {}" ';' 
+1

这是*巨大的*矫枉过正。 – tripleee 2015-08-29 09:29:11

0

由于指挥本地化Tim和诺曼答案应该使用'LANG = C'前缀进行改进,以便有机会与每个具有任何区域参数的系统匹配'无换行'模式

这确保了结束空行把这个脚本的命令行上的每个文件:

#!/bin/sh -f 
for i in $* ; do echo $i; \ 
if LANG=C diff /dev/null "$i" | tail -1 | \ 
    grep '^\\ No newline' > /dev/null; then echo >> "$i"; \ 
fi; done 

而这个脚本检测缺乏的是文件:

#!/bin/sh -f 
for i in $* ; do \ 
if LANG=C diff /dev/null "$i" | tail -1 | \ 
    grep '^\\ No newline' > /dev/null; then echo $i; \ 
fi; done 
1

尝试前路:

ex -s +"bufdo wq" *.c 

,并递归(启用a new globbing option):

ex -s +"bufdo wq" **/*.c 

这相当于vi -es。更改*.c以扩展您的兴趣。

如果不存在,ex/vi会在保存时自动附加新行。

0

找到工具后,做这个工作没有运气。我决定写我自己的

这是我的Python脚本来完成这项工作

只追加(\ r \ n)与文件不包含(\ n)的在文件的结尾

https://github.com/tranhuanltv/append_newline

用法:append_newline.py .C ./projects ./result_dir

制作引入请求,如果你想

+0

这是非常值得怀疑的 - 从END开始寻找-1是可以的,但是你可以用这种方法轻松地混合使用Unix和DOS换行符...... – 2016-04-01 07:26:57

0

我很惊讶没有人已经提到像Awk这样的许多简单的文本处理工具会添加一个换行符作为副作用。这是一个简单的循环,只有在实际添加换行符时才会覆盖文件。

for f in *; do 
    awk 1 "$f" >tmp 
    cmp -s tmp "$f" || mv tmp "$f" 
done 
rm -f tmp 

(临时文件显然是有点疣。)

IDEone演示:http://ideone.com/HpRHcx

0
pcregrep --recursive --exclude-dir=.git \ 
    --files-without-match --multiline '\n\z' . | 
    while read k ; do echo >> "$k"; done 

这里涉及到几个步骤:

  1. 递归查找文件
  2. 检测哪些文件缺乏一个尾随新行
  3. 遍历每个那些文件
  4. 追加新行

步骤1历来与find做(以下 Unix的传统“每个工具做一两件事,做的很好”),但由于pcregrep具有内置的支持,我很舒服使用它。我小心避免乱七八糟的.git文件夹。

步骤2用多正则表达式匹配有一个最后的换行的文件,并打印该匹配文件名来完成。

步骤3是用while/read循环而不是for/in完成的,因为后者失败了包含空格的文件名和极长的文件列表。

步骤4是一个简单的回声,遵循@ norman-ramsey的方法。

h/t @ anthony-bush https://stackoverflow.com/a/20687956/577438为pcregrep建议。

1

我使用find代替for f in *,因为它是递归的,问题是关于“大量的源文件”。

由于性能方面的原因,我使用的是while read而不是find -execxargs,它每次都会节省产卵shell进程。

我正在利用反引号操作符正在返回命令的输出,“任何尾随的换行符被删除”man bash,因此对于正确终止的文件,反引号将为空,并且回显将被跳过。

find | read夫妇将无法对包含换行符的文件名,但它很容易,如果需要解决:

find -type f -print0 | while read -d $'\0' f; do [[ `tail -c1 "$f"` ]] && echo >> "$f"; done

0

下面是我的bash脚本的解决方案。它首先检查文件是否是文本文件。然后,如果它是一个文本文件,它使用tail和od(八进制转储)来查看最后一个字符是否是换行符。如果不是,那么就使用回声附加一个换行符:

item="$1" 

if file "$item" | egrep '\btext\b' > /dev/null 
then 
    if ! tail -c 1 "$item" | od -b -A n | egrep '\b012\b' > /dev/null 
    then 
     echo "(appending final newline to ${item})" 
     echo >> "$item" 
    fi 
fi 
1

一个简单的修正对于那些“失踪”换行符在文件末尾简单的sed文件;以下修复“就地”(使用“-i”选项)的文件:

find . -type f -exec sed -i -e '$a\' {} \; -print 

说明:找到的所有文件(-type f),运行sed,更改文件就地(-i),给定以下(-e)脚本/表达式匹配文件末尾($),并执行“追加”动作(a\),但实际上并未指定要追加的任何文本(在\之后没有任何内容)在文件的末尾添加一个换行符,但只有当文件末尾不存在时。打印找到的所有文件(固定或不固定),这可能是不必要的。

主要需要注意的是sed功能因平台而异,所以-i-e可能会或可能不会被支持/相同;例如较旧的Unix或MacOS的怪异可能需要稍微不同的语法。

相关问题