Git Bash 是 Windows 中安装 Git 时获得的一个不错的 bash shell。它内部捆绑了其他典型的 UNIX 工具,例如 grep、sed、awk、perl。它没有文件命令。
在此 shell 中,我想检测具有 DOS 样式行结尾的文件。我以为这个命令会起作用,但事实并非如此:
grep -l ^M$ *
即使文件没有 CR 行结尾匹配,它也不起作用。例如,如果我创建 2 个示例文件hello.unix
和hello.dos
,我可以确认wc
具有hello.unix
6 个字符,并且hello.dos
由于额外的 CR 而具有 7 个字符,但这两个文件都与grep
.那是:
$ cat hello.*
hello
hello
$ wc hello.*
1 1 7 hello.dos
1 1 6 hello.unix
2 2 13 total
$ grep -l ^M hello.*
hello.dos
hello.unix
grep
这是Git Bash实现中的错误吗?还有另一种方法可以查找所有具有 DOS 风格行结尾的文件吗?
答案1
编辑:愚蠢的我。当然^M就是CR;并且您的命令应该有效(在我的系统上有效)。但是,您需要键入 Ctrl-V Ctrl-M 才能获取文字 '\r'/CR (而不是两个字符^
和M
)。
备择方案:
做这个:
find dir -type f -print0 | xargs -0 grep -l `printf '\r\n'`
或这个:
find dir -type f -print0 | xargs -0 grep -lP '\r\n'
您还可以使用文件实用程序(不确定它是否随 GIT bash 一起提供):
find dir -type f -print0 | xargs -0 file | grep CRLF
答案2
我不知道 git bash,但也许
if [ "$(tr -cd '\r' < file | wc -c)" -gt 0 ]; then
echo there are CR characters in there
fi
会工作。想法是不使用文本可以特殊处理 CR 和 LF 字符的实用程序。
如果这不起作用,那么也许
if od -An -tx1 < file | grep -q 0d; then
echo there are CR characters in there
fi
挂钩查找:
find . -type f -exec sh -c 'od -An -tx1 < "$1" | grep -q 0d' sh {} \; -print
答案3
@sch 引导我找到了这个解决方案:
sed -bne '/\r$/ {p;q}' < /path/to/file | grep -q .
如果文件中有任何以 CR 结尾的行,则以 TRUE 退出。要将其挂钩到 find 中:
find /path/to/ -type f -exec sh -c 'sed -bne "/\r$/ {p;q}" < "$1" | grep -q .' sh {} \; -print
我想我知道为什么grep -l ^M hello.*
在这个 shell 中不起作用:似乎在 Git Bash 中^M
字符被从所有命令行参数中删除,因此grep
永远不会真正接收到该字符,因此所有文件都匹配。这种行为不仅出现在命令行中,而且出现在 shell 脚本中。
所以关键是^M
用其他符号来表达这个字符,比如\r
,而不是字面意思。
答案4
在 Linux/Ubuntu 上使用 file 命令。如果文件是 DOS 格式,输出将包含“with CRLF line terminators”字样。如果文件是 UNIX 格式,则输出中不会出现此类单词。在下面的示例中,del.txt 为 DOS 格式,del 为 UNIX 格式。
$ file del.txt
del.txt: C source, ASCII text, with CRLF line terminators
$ echo "hello" > del
user@decatur2:~/manpuriav$ file del
del: ASCII text