ChatGPT解决这个技术问题 Extra ChatGPT

Windows命令转换Unix行尾?

是否有用于转换文件行尾的 Windows 命令?

我们有一个 test.bat,我们需要运行它来启动我们的服务器。我们使用 Perforce,我们需要在我们的工作空间中有 unix 行尾。出于某种原因,我们不允许在工作区中将行尾更改为 Windows。但是,服务器在 Windows 上运行。

每次我必须运行 bat 文件时,我都会在 Notepad++ 中打开它,然后选择编辑→EOL 转换→Windows。有没有办法自动化这个,这样我们每次与 Perforce 同步时就不需要手动更改行尾?

提前致谢。


A
AbraCadaver

这实际上可以使用 Windows NT 及更高版本中包含的 more 命令非常容易地完成。要将包含 UNIX EOL(行尾)\ninput_filename 转换为包含 Windows EOL \r\noutput_filename,只需执行以下操作:

TYPE input_filename | MORE /P > output_filename

more 命令具有您可能不知道的其他格式选项。运行 more/? 以了解 more 还能做什么。


这似乎为不以换行符结尾的文件添加了一个额外的换行符,如果这对您的特定场景很重要,请注意。
不幸的是,这也将所有制表符都弄乱了。
我需要与此相反。任何想法?
很好的答案!稍微简单一点:more /P <input_file >output_file
@Sebastian 什么是 Windows 9?
D
David Jashi

使用 unix2dos 实用程序。您可以下载二进制文件 here


同样,它只是记事本++的替代品。不会真正让这个自动化。我将不得不运行这个工具。到目前为止,我确实更改了 notepad++ 中的行尾。
它是一个命令行工具。它更适合自动化,然后是 GUI 工具。您可以编写一个定期的 at 作业,它过滤您放置批处理文件的某个文件夹中的所有文件。这完全取决于您所说的自动化是什么意思。
J
Jurosh

我正在处理 CRLF 问题,因此我决定构建非常简单的转换工具(在 NodeJS 中):

这是NodeJS EOL converter CLI

所以如果你有安装了 npm 的 NodeJS,你可以试试:

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

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

因此,如果您可以使用 NodeJS,这真的很简单,您可以集成此命令将整个工作区转换为所需的行尾。


A
Ansgar Wiechers

您可以在 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) 连接起来将其写入文件。


@FranklinYu 使用 PowerShell 方法,您可以将修改后的内容写回同一个文件(Get-Content 周围的括号使这成为可能)。至于一般的“就地”编辑:see here
对于第一个带有 -replace 的 powershell 方法,您必须将 -raw 选项添加到 get-content 以执行您想要的操作。只是不要在同一个文件上做两次。您甚至不需要引用文件名。请注意,在 powershell 5 中使用“>”或“out-file”会产生“unicode”编码文件与“ansi”。
k
kxr

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 脚本和 PATH 中:

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

并使用该工具

any2here UNIXFILE.EXT > MYPLATFILE.EXT

u
uosjead

以 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" )

如果您不想验证每一个更改

移动

移动/y

包括子目录更改

目录 /b

目录 /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\”,这将完全失败。
E
Endoro

尝试这个:

(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..

它有效,但似乎也从文件中删除了所有空行。 :(
@MarioVilas 是的,你是对的。为此,您可以使用 flip
R
Ricardo

我对此的贡献,转换文件夹中的多个文件:for %%z in (*.txt) do (for /f "delims=" %%i in (%%z) do @echo %%i)>%%z.tmp


S
Stephen Quan

如果你有 bash(例如 git bash),你可以使用以下脚本从 unix2dos 转换:

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

同样,从 dos2unix 转换:

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

M
MD XF

您可以创建一个简单的批处理脚本来为您执行此操作:

TYPE %1 | MORE /P >%1.1
MOVE %1.1 %1

然后运行 <batch script name> <FILE><FILE> 将立即转换为 DOS 行尾。


r
retr0

我使用 windows 上的 git bash 克隆了我的 git 项目。然后所有文件都有 LF 结尾。我们的存储库默认有 CRLF 结尾。

我删除了该项目,然后使用 Windows Command Prompt 再次克隆它。 CRLF 结尾是完整的。就我而言,如果我改变了项目的结局,那么它会导致巨大的提交,并会给我的队友带来麻烦。所以,就这样做了。希望这可以帮助某人。


有一种方法可以使用 git 将 CRLF 转换为 LF 我只是使用你的方法来获得 LF 结尾,但我无法让它工作。所以我决定改变 git configs 这里是一个片段: $ git config --global core.autocrlf input
J
Jean-François Larvoire

这是一个简单的 unix2dos.bat 文件,它保留了空行和感叹号:

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

输出到标准输出,因此如果需要,将 unix2dos.bat 输出重定向到文件。

它通过以下方式避免了其他先前提出的 for /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) 使用在行号后插入 findstr /n 的冒号作为echo 命令后的标记分隔符。

我会留给 Jeb 来解释是否存在 echo:something 可能失败的极端情况 :-)
我只能说最后一个版本成功地恢复了我巨大的 batch library 上的行尾,所以例外,如果任何,一定非常罕见!


这会从行首删除所有冒号 :。这会破坏所有批处理功能。顺便提一句。测试以转换具有类似 \..\..\windows\system32\calc.exe 的行的文件。要解决此问题,请查看 this explanation
你是对的!我想做一个 1-liner,比以前发布的解决方案更简单、更好,但显然这做不到。你的是迄今为止唯一正确的。
但是挑战是不可抗拒的,也许我现在找到了另一个 1 行解决方案,如上面编辑过的文本所示 :-)
你又失败了 :-) 用 ..\..\..\..\..\windows\system32\calc.exe 试试。唯一的安全 ECHO 形式是echo(。一个班轮是可能的,但我想这很棘手
Caramba, schon wieder verpaßt!好吧,我暂时放弃。但我相信总有一天,我会成功的! :-)
I
Ir Relevant

根据 Endoro 的回答,但要保留空白,请尝试以下操作:

@echo off
setlocal enabledelayedexpansion
(for /f "tokens=* delims=:" %%i in ('findstr /n "^" file.unix') do (
        set line=%%i
        set line=!line:*:=!
        echo(!line!
        ))>file.dos

Ir Relevant 的解决方案工作正常,只是它去掉了所有感叹号 (!)。
j
jeb

聚会迟到了,但仍然没有使用 FOR /F 循环的正确答案。
(但您根本不需要 FOR 循环,solution from @TampaHaze 也可以工作并且是简单得多)

answer from @IR relevant 有一些缺点。
它去掉了感叹号,也可以去掉插入符号。

@echo off
(
    setlocal Disabledelayedexpansion
    for /f "tokens=* delims=" %%L in ('findstr /n "^" "%~1"') do (
        set "line=%%L"
        setlocal enabledelayedexpansion
        set "line=!line:*:=!"
        (echo(!line!)
        endlocal
    )
) > file.dos

诀窍是使用 findstr /n 在每行前加上 <line number>:,这样可以避免跳过空行或以 ; 开头的行。
要删除 <number>:,不能使用 FOR "tokens=1,* delims=:" 选项,因为这也会删除一行中的所有前导冒号。

因此,行号被 set "line=!line:*:=!" 删除,这需要 EnableDelayedExpansion。
但是对于 EnableDelayedExpansion,行 set "line=%%L" 将删除所有感叹号和插入符号(仅当感叹号在行中时)。

这就是为什么我之前禁用延迟扩展并仅在需要的两条线中启用它。

(echo(!line!) 看起来很奇怪,但有一个优点,即 echo( 可以显示 !line! 中的任何内容,并且外括号避免了行尾的意外空格。


j
jovib

要将 UNIX(LF) 转换为 Windows(CR-LF),请在 Windows 终端上使用下一个命令。

type file.txt > new_file.txt

R
RHenningsgard

我正在参加 AWS 课程,并且经常不得不从 AWS Web 表单中的文本框复制到 Windows 记事本。所以我只在我的剪贴板上得到了 LF 分隔的文本。我偶然发现将它粘贴到我的 Delphi 编辑器中,然后按 Ctrl+K+W 会将文本写入带有 CR+LF 分隔符的文件。 (我敢打赌许多其他 IDE 编辑器也会这样做)。


J
Jimmy Smith

Inserting Carriage Returns to a Text File

@echo off
set SourceFile=%1 rem c:\test\test.txt
set TargetFile=%2 rem c:\test\out.txt

if exist "%TargetFile%" del "%TargetFile%"
for /F "delims=" %%a in ('type "%SourceFile%"') do call :Sub %%a
rem notepad "%TargetFile%"
goto :eof


:Sub
echo %1 >> "%TargetFile%"
if "%2"=="" goto :eof
shift
goto sub

实际上,如果他只使用 (for /f "tokens=*" %%a in (%~1) do @echo.%%a)>"%~2" 之类的东西就可以了。
@AnsgarWiechers 是的,这个 set TargetFile=%2 rem c:\test\out.txt 也需要改进。而且,顺便说一句,你的 "tokens=*" 也是。
@Endoro REM 是批处理文件中的注释,您可以取出 %1 rem 然后给它您需要的特定文件。当我提供链接时,我觉得我不需要进一步记录,因为您已经在使用批处理文件,对吗?请对其进行测试,因为它确实有效,并且可以随意集成到您现有的批处理文件中。谢谢!
在 Windows 7 中工作正常。我在 Notepad++ 中使用来自 Unix 的 EOL 创建了一个文件 c:\test\test.txt。之后,我只是运行了批处理文件。再说一遍,这不是我的代码,是我稍微修改后不显示记事本的代码?我可以向 OP 展示如何使其工作,而不是最后的评论。