将Unix行结尾转换为Windows格式的命令?

86

有没有Windows命令可以转换文件的行结尾?

我们有一个需要运行来启动服务器的 test.bat 文件。 我们使用Perforce,并且我们需要在工作区中拥有Unix行结尾。由于某种原因,我们不被允许将行结尾更改为Windows。但是,服务器在Windows上运行。

每次我必须运行bat文件时,我都会在Notepad ++中打开它,然后选择Edit→EOL conversion→Windows。 有没有一种自动化这个过程的方法,以便我们不需要每次与Perforce同步时手动更改行结尾?

19个回答

73

使用Windows NT及更高版本中包含的more命令可以轻松地完成此操作。要将包含UNIX EOL(行尾结束符)\ninput_filename转换为包含Windows EOL\r\noutput_filename,只需执行以下操作:

TYPE input_filename | MORE /P > output_filename

more 命令有一些额外的格式选项,你可能不知道。使用 more/? 命令来了解 more 的其他功能。


5
如果这对你的特定场景有影响的话,需要提醒一下:这似乎会向没有以换行符结尾的文件中添加额外的换行符。 - aolszowka
4
不幸的是,这也会使所有的制表符被转换为空格。 - Colin
4
我需要相反的东西,有什么想法吗? - Ross Brigoli
4
好的回答!稍微简单一点:more /P <input_file >output_file - Dimagog
6
@Sebastian Windows 9是什么? - MD XF
显示剩余4条评论

35

1
这只是Notepad++的替代品。无法自动完成此操作,我必须运行此工具。目前我在Notepad++中更改行尾。 - Deepti Jain
12
这是一个命令行工具。相较于图形界面工具,它更适用于自动化。你可以编写定期的 at 作业,筛选你放置批处理文件的某个文件夹中的所有文件。一切都取决于你对自动化的定义。 - David Jashi

21

我曾处理过 CRLF 问题,因此决定创建一个非常简单的转换工具(在NodeJS中):

它就是 NodeJS EOL converter CLI

如果你已经安装了带npm的NodeJS,你可以试用它:

npm i -g eol-converter-cli
eolConverter crlf "**/*.{txt,js,java,etc}"

可以使用Glob正则表达式(与shell中相同的正则表达式)来动态配置路径。

因此,如果您可以使用NodeJS,则非常简单,并且可以将此命令集成到将整个工作区转换为所需行结束符的过程中。



16

您可以在VBScript中不需要额外的工具来实现这一点:

Do Until WScript.StdIn.AtEndOfStream
  WScript.StdOut.WriteLine WScript.StdIn.ReadLine
Loop

将上述代码放入一个名为unix2dos.vbs的文件中,然后像下面这样运行它:
cscript //NoLogo unix2dos.vbs <C:\path\to\input.txt >C:\path\to\output.txt

或者像这样:
type C:\path\to\input.txt | cscript //NoLogo unix2dos.vbs >C:\path\to\output.txt

你也可以在PowerShell中完成:

(Get-Content "C:\path\to\input.txt") -replace "`n", "`r`n" |
  Set-Content "C:\path\to\output.txt"

这可以进一步简化为:
(Get-Content "C:\path\to\input.txt") | Set-Content "C:\path\to\output.txt"

上述语句在不需要显式替换的情况下工作,因为Get-Content会将输入文件隐式分割为任何类型的换行符(CR、LF 和 CR-LF),而Set-Content则会在将输入数组与 Windows 换行符(CR-LF)连接后再将其写入文件。

2
@FranklinYu 通过PowerShell方法,您可以将修改后的内容写回到同一文件中(Get-Content周围的括号使此操作成为可能)。至于一般的“原地”编辑:请参见此处 - Ansgar Wiechers
对于第一个使用-replace的PowerShell方法,您需要添加-raw选项到get-content中以实现您的意图。只是不要在同一个文件上执行两次。您甚至不需要引用文件名。请注意,在PowerShell 5中使用“>”或“out-file”会导致“unicode”编码文件而不是“ansi”。 - js2010

12

Windows的MORE命令并不可靠,它会不可避免地破坏TAB并添加行。

unix2dos也是MinGW/MSYS、Cygutils、GnuWin32和其他Unix二进制端口集合的一部分 - 也可能已经安装好了。

当有python时,此单行代码可以将任何行尾转换为当前平台 - 在任何平台上都可以:

TYPE UNIXFILE.EXT | python -c "import sys; sys.stdout.write(sys.stdin.read())" > MYPLATFILE.EXT
或者
python -c "import sys; sys.stdout.write(open(sys.argv[1]).read())" UNIXFILE.EXT > MYPLATFILE.EXT

或者将这个一行命令放入一个.bat / shell脚本,并根据您的平台将其添加到环境变量中:

@REM This is any2here.bat
python -c "import sys; sys.stdout.write(open(sys.argv[1]).read())" %1

然后像使用那个工具一样使用它

any2here UNIXFILE.EXT > MYPLATFILE.EXT

8

在 TampaHaze 和 MD XF 有用的回答的基础上进行。

这将在命令提示符中将当前目录中所有 .txt 文件从 LF 改为 CRLF,原地更改。

for /f "delims=" %f in ('dir /b "*.txt"') do ( type "%f" | more /p > "%f.1" & move "%f.1" "%f" )

如果您不想验证每一个更改,
请使用以下命令:
移动文件夹:
move /y
包括子目录的文件夹:
dir /b /s
如果您想在批处理文件中执行所有操作,包括子目录,而不提示“.txt”文件,请使用以下命令。
@echo off
setlocal enabledelayedexpansion

for /f "delims=" %%f in ('dir /s /b "*.txt"') do (
    type "%%f" | more /p > "%%f.1"
    move /y "%%f.1" "%%f" > nul
    @echo Changing LF-^>CRLF in File %%f
)
echo.
pause

如果文件路径中包含空格(例如“C:\Program Files\FileMaker\FileMaker Server\HTTPServer\conf\”),则此方法将完全失败。 - John Smith

6

试一下这个:

(for /f "delims=" %i in (file.unix) do @echo %i)>file.dos

会话协议:

C:\TEST>xxd -g1 file.unix
0000000: 36 31 36 38 39 36 32 39 33 30 38 31 30 38 36 35  6168962930810865
0000010: 0a 34 38 36 38 39 37 34 36 33 32 36 31 38 31 39  .486897463261819
0000020: 37 0a 37 32 30 30 31 33 37 33 39 31 39 32 38 35  7.72001373919285
0000030: 34 37 0a 35 30 32 32 38 31 35 37 33 32 30 32 30  47.5022815732020
0000040: 35 32 34 0a                                      524.
C:\TEST>(for /f "delims=" %i in (file.unix) do @echo %i)>file.dos
C:\TEST>xxd -g1 file.dos 0000000: 36 31 36 38 39 36 32 39 33 30 38 31 30 38 36 35 6168962930810865 0000010: 0d 0a 34 38 36 38 39 37 34 36 33 32 36 31 38 31 ..48689746326181 0000020: 39 37 0d 0a 37 32 30 30 31 33 37 33 39 31 39 32 97..720013739192 0000030: 38 35 34 37 0d 0a 35 30 32 32 38 31 35 37 33 32 8547..5022815732 0000040: 30 32 30 35 32 34 0d 0a 020524..

1
它能够工作,但似乎也从文件中删除了所有的空行。 :( - MarioVilas
2
@MarioVilas 是的,你说得对。你可以使用flip来实现这个功能。 - Endoro

3

如果您拥有 Bash(例如 Git Bash),您可以使用以下脚本将 Unix 转换为 DOS:

ex filename.ext <<EOF
:set fileformat=dos
:wq
EOF

同样地,要将文本从dos格式转换为unix格式:
ex filename.ext <<EOF
:set fileformat=unix
:wq
EOF

3

以下是我的贡献,将文件夹中的多个文件进行转换:

for %%z in (*.txt) do (for /f "delims=" %%i in (%%z) do @echo %%i)>%%z.tmp

2
这是一个简单的unix2dos.bat文件,可以保留空行和感叹号:
@echo off
setlocal DisableDelayedExpansion
for /f "tokens=1,* delims=:" %%k in ('findstr /n "^" %1') do echo.%%l

输出将发送到标准输出,如果需要的话,将 unix2dos.bat 的输出重定向到文件。

它通过以下方式避免了其他先前提出的 /f 批处理循环解决方案的缺陷:
1)延迟扩展关闭工作,以避免使用感叹号。
2)使用 for /f 分词器本身从 findstr /n 输出行中删除行号。
(使用 findstr /n 是必要的,以获取空白行:如果 for /f 直接从输入文件中读取,则会丢弃它们。)

但是,正如 Jeb 在下面的评论中指出的那样,上述解决方案有一个其他解决方案没有的缺点:它会丢弃行首的冒号。

所以 2020-04-06 更新只是为了好玩,这里是另一种基于 findstr.exe 的 1-liner,似乎可以在没有上述缺点的情况下正常工作:

@echo off
setlocal DisableDelayedExpansion
for /f "tokens=* delims=0123456789" %%l in ('findstr /n "^" %1') do echo%%l

额外的技巧包括:
3)使用数字0-9作为分隔符,这样tokens=*将跳过初始行号。
4)在echo命令后使用冒号,由findstr /n插入行号后作为标记分隔符。

我会让Jeb解释是否存在echo:something可能失败的边界情况:-)
我只能说,这个最新版本成功地恢复了我巨大的batch library中的行尾,因此任何异常情况都应该非常罕见!


这将从每行开头删除所有冒号“:”。这会破坏所有批处理函数。另外,测试一下是否可以将文件转换为包含类似于“....\ windows \ system32 \ calc.exe”这样的行。要解决此问题,请参阅此解释 - jeb
但是这个挑战是不可抗拒的,也许我现在已经找到了另一个一行解决方案,就像上面编辑的文本所示 :-) - Jean-François Larvoire
天啊,Windows 真是要求太多了,这么多的 "if、and、or 和 but",我根本无法跟进。我从来没有想过,在开发整个自定义 PHP 数据库视图时最耗费时间的部分竟然是在将完成的项目复制到服务器后处理行末标识符。难道没有 Windows 工具可以解决这个极其常见的问题吗?不需要那么费脑筋吧! - John Smith
更新:我用Notepad++完成了。 - John Smith
@John Smith:针对Windows,有很多Unix2dos和Dos2unix程序的端口,可以轻松解决最初的问题。请参见kxr在https://dev59.com/sWMm5IYBdhLWcg3wfu82#35661818中的回答以获取详细信息。 这里,仅出于艺术的目的,我试图使用一个简短的Windows批处理脚本来完成它。如果可能的话,在这种可怜的脚本语言中非常难做到这一点。但正是这种困难使我们中的一些人觉得这是一个有趣的挑战。 :-) - Jean-François Larvoire
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接