Ada*_*ski 77 bash text-processing newlines
我需要定期运行一个命令,以确保某些文本文件保持在 Linux 模式下。不幸的是dos2unix总是修改文件,这会弄乱文件和文件夹的时间戳并导致不必要的写入。
我编写的脚本是用 Bash 编写的,所以我更喜欢基于 Bash 的答案。
Sam*_*ard 52
您可以dos2unix用作过滤器并将其输出与原始文件进行比较:
dos2unix < myfile.txt | cmp - myfile.txt
Run Code Online (Sandbox Code Playgroud)
Gyp*_*aut 47
用 cat -A
$ cat file
hello
hello
Run Code Online (Sandbox Code Playgroud)
现在,如果这个文件是在 *NIX 系统中制作的,它将显示
$ cat -A file
hello$
hello$
Run Code Online (Sandbox Code Playgroud)
但是如果这个文件是在 Windows 中制作的,它会显示
$ cat -A file
hello^M$
hello
Run Code Online (Sandbox Code Playgroud)
^M代表CR和$代表LF。请注意,Windows 没有保存最后一行CRLF
这也不会更改文件内容。
注意:这不应该在自动化脚本中使用,只是为了快速检查。对于自动化脚本,我建议您查看@Samuel Edwin Ward 的答案
j88*_*376 27
如果目标只是为了避免影响时间戳,dos2unix则使用-kor--keepdate选项可以保持时间戳不变。它仍然需要写入以制作临时文件并重命名它,但您的时间戳不会受到影响。
如果对文件的任何修改是不可接受的,您可以使用此答案中的以下解决方案。
find . -not -type d -exec file "{}" ";" | grep CRLF
Run Code Online (Sandbox Code Playgroud)
don*_*sti 24
您可以尝试使用grep八进制的 CRLF 代码:
grep -U $'\015' myfile.txt
Run Code Online (Sandbox Code Playgroud)
或十六进制:
grep -U $'\x0D' myfile.txt
Run Code Online (Sandbox Code Playgroud)
小智 23
由于版本7.1dos2unix 有一个-i,--info选项来获取有关换行符的信息。您可以使用 dos2unix 本身来测试哪些文件需要转换。
例子:
dos2unix -ic *.txt | xargs dos2unix
Run Code Online (Sandbox Code Playgroud)
Ber*_*rtS 17
grep):计算包含回车的行数:
[[ $(grep -c $'\r' myfile.txt) -gt 0 ]] && echo dos
Run Code Online (Sandbox Code Playgroud)
计算以回车符结尾的行数:
[[ $(grep -c $'\r$' myfile.txt) -gt 0 ]] && echo dos
Run Code Online (Sandbox Code Playgroud)
这些通常是等效的;在一行的内部(即不在末尾)回车是很少见的。
更高效:
grep -q $'\r' myfile.txt && echo dos
Run Code Online (Sandbox Code Playgroud)
这样效率更高
grep -c需要读取整个文件,计算模式的所有出现次数,同时grep -q可以在看到模式第一次出现时退出。笔记:
-U选项(即使用-cU或-qU),因为 GNU 会grep猜测该文件是否为文本文件。如果它认为文件是文本,它会忽略行尾的回车符,试图使$正则表达式“正确”工作——即使正则表达式是\r$! 指定-U(或--binary) 否决了这种猜测,导致grep将文件视为二进制文件并将数据逐字传递给匹配机制,CR 结尾完好无损。grep … $'\r\n' myfile.txt,因为grep将其\n视为模式分隔符。就像grep -E 'foo|'查找包含foo或 空字符串的行一样,
grep $'\r\n'查找包含\r或 空字符串的行,并且每一行都匹配一个空字符串。file):[[ $(file myfile.txt) =~ CRLF ]] && echo dos
Run Code Online (Sandbox Code Playgroud)
因为file报告如下:
myfile.txt: UTF-8 Unicode text, with CRLF line terminators
Run Code Online (Sandbox Code Playgroud)
更安全的变体:
[[ $(file -b - < myfile.txt) =~ CRLF ]] && echo dos
Run Code Online (Sandbox Code Playgroud)
在哪里
file -b只输出文件类型,不输出文件名。没有这一点,一个文件,其名称包含字符CRLF
会触发误报。file - < filename即使filename以-.
请参阅Bash 脚本:检查文件是否为文本文件。请注意,检查来自 的输出file
可能不适用于非英语语言环境。
为您提供 bash 功能:
# return 0 (true) if first line ends in CR
isDosFile() {
[[ $(head -1 "$1") == *$'\r' ]]
}
Run Code Online (Sandbox Code Playgroud)
然后你可以做类似的事情
streamFile () {
if isDosFile /tmp/foo.txt; then
sed 's/\r$//' "$1"
else
cat "$1"
fi
}
streamFile /tmp/foo.txt | process_lines_without_CR
Run Code Online (Sandbox Code Playgroud)
小智 6
使用file:
$ file README.md
README.md: ASCII text, with CRLF line terminators
$ dos2unix README.md
dos2unix: converting file README.md to Unix format...
$ file README.md
README.md: ASCII text
Run Code Online (Sandbox Code Playgroud)
如果文件具有 DOS/Windows 样式的 CR-LF 行结尾,那么如果您使用基于 Unix 的工具查看它,您将在每行末尾看到 CR ('\r') 字符。
这个命令:
grep -l '^M$' filename
Run Code Online (Sandbox Code Playgroud)
如果文件包含一行或多行带有 Windows 样式行结尾的行,则将打印filename,否则将不打印任何内容。只不过^M必须是文字回车符,通常通过键入Ctrl+V后跟Enter
(或Ctrl+V然后Ctrl+ M)在终端中输入。bash shell 允许您编写文字回车符$'\r'(此处记录),因此您可以编写:
grep -l $'\r$' filename
Run Code Online (Sandbox Code Playgroud)
其他外壳可能提供类似的功能。
您可以使用其他工具代替:
awk '/\r$/ { exit(1) }' filename
Run Code Online (Sandbox Code Playgroud)
如果文件包含任何 Windows 样式的行结尾,则这将以状态退出1(设置$?为),如果不包含,1则状态为,使其在 shell语句中有用(注意缺少括号):0if[]
if awk '/\r$/ { exit(1) }' filename ; then
echo filename has Unix-style line endings
else
echo filename has at least one Windows-style line ending
fi
Run Code Online (Sandbox Code Playgroud)
文件可以包含 Unix 样式和 Windows 样式的混合行结尾。我在这里假设您想要检测具有任何Windows 样式行结尾的文件。