批处理文件:如何读取文件?

116

如何从批处理文件中读取文件(文本或二进制文件)?有没有一种方法可以在二进制模式或文本模式下读取它?


@RookieTEC9:是的,我知道它们是两个完全不同的东西,但我需要一个在msdos中有效的答案,而不是在Windows NT(或更新版本)中,此外这个问题是7年前提出的,请记住这一点。 - Lucas Gabriel Sánchez
@RookieTEC9:我认为你是对的,这已经有一段时间了。我会删除ms-dos标签。 - Lucas Gabriel Sánchez
1
你可以在 MS-Dos 中使用命令 TYPE [fileName] - Roke
试一下这个,对我有效 - https://dev59.com/2Y3da4cB1Zd3GeqP6ezJ#31919715 - Anurag_BEHS
7个回答

86

在NT-style的cmd.exe环境下,你可以使用以下代码循环遍历文本文件中的每一行:

FOR /F %%i IN (file.txt) DO @echo %%i

在命令提示符上键入"help for"以获取更多信息(不知道你正在使用的任何"DOS"是否有效)。


41
如果发现一个空格字符,该命令将停止读取一行。最终我使用了FOR /F "tokens=*" %%i IN (file.txt) DO @ECHO %%i。 - Jason
11
它有效!如果您正在使用控制台,请尝试%i;如果您正在使用批处理文件,则请尝试%%i。 - Steven Du

46

FOR循环通常有效,但存在一些问题。FOR不接受空行和长度超过~8190的行存在问题。 如果延迟扩展被禁用,则仅可靠地进行扩展。

CR/LF与单个LF的检测也似乎有点复杂。
此外,NUL字符是有问题的,因为FOR循环会立即取消读取。

直接二进制读取因此几乎不可能。

空行的问题可以通过一个技巧来解决。使用findstr命令在每行前缀中添加行号,并在读取后删除前缀。

@echo off
SETLOCAL DisableDelayedExpansion
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ t.txt"`) do (
    set "var=%%a"
    SETLOCAL EnableDelayedExpansion
    set "var=!var:*:=!"
    echo(!var!
    ENDLOCAL
)

在处理字符串时,如!^^^xy!z,必须在启用和禁用延迟扩展之间切换。这是因为只有在DisabledDelayedExpansion的情况下,才可安全使用set "var=%%a"这行代码,否则感叹号将被删除,插入符号将被用作(二级)转义字符并也会被删除。
但是,仅在EnabledDelayedExpansion的情况下,使用变量var是安全的,因为即使像"&"&这样的内容使用call %%var%%也会失败。

编辑:添加了set/p变体
有第二种使用set /p读取文件的方法,唯一的缺点是每行限制在约1024个字符,并且它会删除行尾的控制字符。
但是它的优点是您不需要切换延迟,而且更容易将值存储在变量中。

@echo off
setlocal EnableDelayedExpansion
set "file=%~1"

for /f "delims=" %%n in ('find /c /v "" %file%') do set "len=%%n"
set "len=!len:*: =!"

<%file% (
  for /l %%l in (1 1 !len!) do (
    set "line="
    set /p "line="
    echo(!line!
  )
)

如果要将二进制读入并转换为十六进制表示
你可以参考SO:使用批处理文件将二进制文件转换为十六进制表示


感谢您关于使用 set /p 的指导。我使用了 set /p value=< result.txt 从文本文件中获取第一行。 - SteveC
Jeb,我根据您上面的解决方案提出了一个相关问题,链接为http://stackoverflow.com/questions/11408295/with-dos-batch-file-how-to-parse-a-file-and-output-part-to-one-file-part-to-an。请帮忙查看一下。 - Nicholas
EOF(文件结尾)字符ASCII 0x1A怎么办?for /F与NUL(0x00)字符的行为是否相同? - aschipfl
@aschipfl 我想0x1A在某些情况下的行为类似于换行符(或者更好的是被转换为换行符)。有没有一种方法可以创建一个不使用临时文件的SUB? - jeb
1
这应该是接受的答案,即使行以 :; 开始或包含 ! - ScriptKidd

39

你可以使用for命令:

FOR /F "eol=; tokens=2,3* delims=, " %i in (myfile.txt) do @echo %i %j %k

类型

for /?

在命令提示符处。此外,您可以解析ini文件


32
这是一个相当复杂的例子,从格式特定的文本文件中解析非常具体的信息,没有做任何解释。根据for /?命令的说明,该命令会解析myfile.txt中的每一行,忽略以分号开头的行,并将每行的第二个和第三个标记传递到for循环体中,标记由逗号和/或空格分隔。 - Martin Prikryl
4
你所举的例子来自于cmd.exe的帮助文档。你应该加上一个提示或复制整个描述。 - Th. Thielemann

18

有一个非常简单的方法,就是使用以下命令:

set /p mytextfile=< %pathtotextfile%\textfile.txt
echo %mytextfile%

这将仅显示文本文件中的第一行。您可以使用以下命令进行操作:

type %pathtotextfile%\textfile.txt

这将把文本文件中的所有数据放在屏幕上。希望能帮到您!


这里有一个非常大的危险:这条线的限制是1023个字符。因此,set /p 只会读取前1023个字符。如果你能在你的回答中加上这个,那就太棒了。 - undefined

2

settings.ini

name="John"
lastName="Doe"

script.bat

@echo off
for /f "tokens=1,2 delims==" %%a in (settings.ini) do (
    if %%a==name set %%a=%%b
    if %%a==lastName set %%a=%%b
)

echo %name% %lastName%

1
这可能是一个解决方案,但不是所问的问题的答案。 - jeb

1

有很多种方法,但如果你只想显示文本而不想在任何地方存储它,那么你只需使用:findstr /v "randomtextthatnoonewilluse" filename.txt


0

修正后的代码:

setlocal enabledelayedexpansion
for /f "usebackq eol= tokens=* delims= " %%a in (`findstr /n ^^^^ "name with spaces.txt"`) do (
    set line=%%a
    set "line=!line:*:=!"
    echo(!line!
)
endlocal
pause

网页的主要代码。引号位置不正确,该代码不适用于带有空格名称的文件。我的文件名中有空格,我在这里介绍了“^^^^”的技巧。 - Celes
你对文件名加引号的做法是正确的,但你的代码有些问题:eol=delims= 是多余的,set line=%%a 应该使用引号。此外,如果不切换延迟环境变量扩展模式,代码不能读取感叹号。 - jeb

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