如何列出不以换行符结尾的普通文本(.txt
)文件名?如何列出不以换行符结尾的文件?
例如为:列表(输出)这个文件名:
$ cat a.txt
asdfasdlsad4randomcharsf
asdfasdfaasdf43randomcharssdf
$
,并没有列出(输出)这个文件名:
$ cat b.txt
asdfasdlsad4randomcharsf
asdfasdfaasdf43randomcharssdf
$
如何列出不以换行符结尾的普通文本(.txt
)文件名?如何列出不以换行符结尾的文件?
例如为:列表(输出)这个文件名:
$ cat a.txt
asdfasdlsad4randomcharsf
asdfasdfaasdf43randomcharssdf
$
,并没有列出(输出)这个文件名:
$ cat b.txt
asdfasdlsad4randomcharsf
asdfasdfaasdf43randomcharssdf
$
这是缺憾;肯定有人可以做得更好:
for f in `find . -name '*.txt' -type f`; do
if test `tail -c 1 "$f" | od -c | head -n 1 | tail -c 3` != \\n; then
echo $f;
fi
done
N.B.这回答了标题中的问题,它与正文中的问题不同(正在查找以\ n \ n结尾的文件)。
这应该做的伎俩:
#!/bin/bash
for file in `find $1 -type f -name "*.txt"`;
do
nlines=`tail -n 1 $file | grep '^$' | wc -l`
if [ $nlines -eq 1 ]
then echo $file
fi
done;
这样调用它:./script dir
例如./script /home/user/Documents/
- >列出/home/user/Documents
以\n
结尾的所有文本文件。
第一个改进是在之前放置'IFS = $'\ n'`。它允许用空格处理文件。第二个改进是用`$ nlines -eq 0`替换`$ nlines -eq 1`,因为作者需要“文件名,**不会以换行符结束**”。 – 2015-04-17 12:52:58
试试这个:
find -type f -exec sh -c '[ -z "$(sed -n "\$p" "$1")" ]' _ {} \; -print
将打印为空白行结尾的文件的文件名。要打印未以空行结尾的文件,请将-z
更改为-n
。
如果存在包含空格的文件名,那么使用`for ... find ... do`的答案将会失败。 – 2011-01-07 23:33:45
你对'for .. find..`正确。http://mywiki.wooledge.org/BashPitfalls#for_i_in_.24.28ls_.2A.mp3.29 – jfs 2011-01-07 23:46:01
另一种选择:
$ find . -name "*.txt" -print0 | xargs -0I {} bash -c '[ -z "$(tail -n 1 {})" ] && echo {}'
由于您的问题有perl的标签,我会后它使用一个答案吧:
find . -type f -name '*.txt' -exec perl check.pl {} +
其中check.pl如下:
#!/bin/perl
use strict;
use warnings;
foreach (@ARGV) {
open(FILE, $_);
seek(FILE, -2, 2);
my $c;
read(FILE,$c,1);
if ($c ne "\n") {
print "$_\n";
}
close(FILE);
}
这个Perl脚本只是打开一个,每次一个,作为参数传递的文件和只读倒数第二个字符;如果它不是换行符,它只是打印出文件名,否则它什么也不做。
使用pcregrep,grep的的Perl兼容的正则表达式版本使用,如果最后一行有一个换行符,可以用来匹配(或不匹配)-M标志,它支持多行模式:
pcregrep -LMr '\n$' .
在上面的例子中,我们要求在当前目录(.
)中递归搜索(-r
)列出不匹配的文件(-L
)我们的多行(-M
)正则表达式在文件末尾寻找换行符('\n$'
)
更改-L
到-l
会列出做其中有新行的文件。
好吧轮到我了,我给它一个尝试:
find -type f -print0 | xargs -0 -L1 bash -c 'test "$(tail -c 1 "$0")" && echo "No new line at end of $0"'
这个例子对我的作品在OSX(许多上述溶液中没有)
for file in `find . -name "*.java"`
do
result=`od -An -tc -j $(($(ls -l $file | awk '{print $5}') - 1)) $file`
last_char=`echo $result | sed 's/ *//'`
if [ "$last_char" != "\n" ]
then
#echo "Last char is .$last_char."
echo $file
fi
done
本页面上的大多数解决方案都不适合我(FreeBSD 10.3 amd64)。伊恩·威尔的 OSX解决方案确实几乎总是工作,但相当难走: - (
有一个简单的解决方案,它几乎总是工作过:(如果$ f是文件):sed的
-i'-e“$ A \”“$ F”
有一个与sed的解决方案的一个主要问题:它永远不会让你有机会 只检查(而不是追加一个换行符)
上述两种解决方案对于DOS文件都是失败的,我认为最可行的解决方案就是prob 我自己开发的: - )
这里是基本的sh脚本,它结合了file/unix2dos/tail。在 生产,你可能需要在引号中,用“$ F”和取尾输出 (嵌入名为最后的shell变量)为\“$ F \”
if file $f | grep 'ASCII text' > /dev/null; then
if file $f | grep 'CRLF' > /dev/null; then
type unix2dos > /dev/null || exit 1
dos2unix $f
last="`tail -c1 $f`"
[ -n "$last" ] && echo >> $f
unix2dos $f
else
last="`tail -c1 $f`"
[ -n "$last" ] && echo >> $f
fi
fi
希望这可以帮助别人。
你只是在寻找一个文件夹的文件的宽屏幕显示下来?你的问题不是很清楚上面的例子.. – James 2011-01-07 23:05:56
“正常txt”是什么意思?你是在谈论以*空行*(\ n \ n)结尾的文件还是只以换行符结尾的文件?您可以使用`od -c filename`来打印文件的明确表示。 – jfs 2011-01-07 23:42:30
只是为了强调:换行符*不与*空白*行相同。换行符是一个单独的字符 - 它划定了我们所看到的“行”。空白行只是一个没有字符的“行”,通常是2个连续的换行符,没有任何中间字符,或者是以换行符开始的文件中的第一行。有些人呼叫仅包含空格“空白”行的行,并为2个连续换行字符保留“空行”一词。你应该清楚你想要什么。 – jw013 2013-07-18 21:00:22