批处理脚本在最后合并没有Hex char 1A的文件

时间:2012-03-14 10:19:54

标签: batch-file

我正在通过像这样的简单批处理脚本合并两个ASCII文件

COPY a.txt+b.txt c.txt /y /a

问题是,C中的最后一个字符被设置为1A,即SUB的HEX表示法。 c.txt被送入另一个不喜欢最后1A的可执行文件。

生成c.txt之后,如果我在Notepad ++中打开它并删除最后一个字符,那么该文件就可以正常工作。

我怎样才能合并a.txtb.txt1A没有c.txt附加到{{1}}的末尾?

5 个答案:

答案 0 :(得分:29)

放置/a/b开关至关重要。它们的执行方式不同,具体取决于它们是放在源文件名还是目标文件名之后。

当与目标文件名一起使用时,/a会导致添加文​​件结束标记(ASCII 26)。你实际上是在指定这个!

与源文件名一起使用时,

/a指定文件是ASCII并且它被复制到但不包括第一个ASCII 26文件结束标记。该字符及其后的任何内容都会被忽略。

/b会导致整个文件被复制,包括任何文件结束标记及其后的任何内容。

与目标文件名一起使用时,

/a导致ASCII 26被添加为最后一个字符。

/b不会将ASCII 26添加为最后一个字符。

您的解决方案

...虽然我没有测试过,但可能会使用

COPY a.txt+b.txt /a c.txt /b /y

答案 1 :(得分:1)

您可以将开关/a(ASCII-Text)更改为/b(二进制)
另请参阅copy /?

所以生成的命令是

COPY a.txt+b.txt c.txt /y /b

答案 2 :(得分:1)

copy更改为type

type a.txt>c.txt
type b.txt>>c.txt

答案 3 :(得分:1)

我认为@Andrew的样本是错的,但实际上它比我的更正确。

问题是,[/A | /B]说明符可以双向工作。 这有点让人困惑。 copy /?显示[/ A | / B]在第一个源文件之前,也在每个其他源之后以及在目标之后

  

COPY ... [/ A | / B]来源[/ A | / B] [+来源[/ A | / B] ...] [目的地[/ A | / B]]

说明符实际上适用于之前的文件,但也适用于其后的所有文件,包括目标。 但只有直到在命令行上找到相反的说明符,在这种情况下,后面的说明符适用于它之后的所有文件,但也适用于之前的文件。

将复制命令默认值组合为ASCII
样品。

copy aa + bb + cc dd
ASCII ASCII ASCII ASCII

指定要复制为二进制文件的所有文件,接下来的三个样本具有相同的效果:

copy /b aa + bb + cc dd
bin bin bin bin

copy aa /b + bb + cc dd
bin bin bin bin

copy aa + /b bb + cc dd
bin bin bin bin

还有一些测试:

copy aa + bb /a + cc dd
ASCII ASCII ASCII ASCII

copy aa + bb /b + cc dd
ASCII BIN BIN BIN

copy /b aa + bb + cc dd /a
bin bin bin ascii

copy aa /a + bb + cc dd /b
ASCII ASCII ASCII bin

copy aa + bb + cc dd /b
ASCII ASCII ASCII bin

copy aa + bb + cc /a dd /b
ASCII ASCII ASCII bin

但是如果重新使用source作为目标,则目标类型将覆盖同一文件上的源类型:

copy aa + bb + cc aa /b
BIN ASCII ASCII BIN

copy aa + bb + cc /b aa
BIN ASCII BIN BIN

这意味着我的原始示例实际上是将所有文件复制为二进制文件,并且覆盖了开头的/ A.现在它也在做同样的事情,但它看起来更好。

@Andrew示例正在做他所承诺的事情,只是/ A在那里没用。

如果要将一个文件添加到另一个文件,则不需要第三个文件。再次使用第一个作为目的地。不能成为第二个,或者在阅读之前你会覆盖它。

这是我用来连接文件列表中所有文本文件的脚本。

@echo off

set concatenated=final.js

pushd %~dp0

set error=
copy nul "%concatenated%"
if errorlevel 1 set error=true

for /f %%a in (filelist.txt) do (
    echo. && echo.
    echo.   *** %%a
    copy /B /V "%concatenated%" + "%%a" "%concatenated%"
    if errorlevel 1 set error=true
)

popd
echo.
if defined error (echo.   !!!!!!!!!  THERE WERE ERRORS  !!!!!!!!!!
) else echo.   ***  ALL DONE  ***
echo.
pause
exit /b 

答案 4 :(得分:1)

https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/copy

如果/ a在命令行上位于文件列表的前面或后面,则它将 适用于列出的所有文件,直到复制遇到/ b。在这种情况下,/ b 适用于/ b之前的文件。

/ a的效果取决于它在命令行字符串中的位置:- 如果/ a跟随源,则copy命令将文件视为ASCII 文件并复制第一个文件结尾字符之前的数据 (CTRL + Z)。 -如果/ a跟随目标,则copy命令将添加一个 文件结尾字符(CTRL + Z)作为文件的最后一个字符。

如果/ b指示命令解释器读取字节数 由目录中的文件大小指定。 / b是默认值 复制,除非复制合并文件。

如果/ b在命令行上在文件列表之前或之后,它将 适用于所有列出的文件,直到副本遇到/ a。在这种情况下,/ a 适用于/ a之前的文件。

这是一条冗长的说法: 合并文件时的默认值为/ a。 这意味着/ a选项在您的代码段中是多余的,并且无论/ a放在何处都将应用。

解决方案是使用/ b,这指示它在读取时忽略#1A [DOS文件结尾]字符,并且在写入时不输出。

与/ a不同,如果源文件包含#1A字符,则/ b的位置很重要。如果/ b在命令末尾,则文件将被截断到#1A(但不包括#1A)。

以下任何一项都可以纠正此行为:

COPY a.txt+b.txt c.txt /y /b
COPY a.txt+b.txt /b c.txt /y
COPY /b a.txt+b.txt c.txt /y

但是在不使用DOS文件结尾表示文件结尾的情况下,只有以下内容才有效:

COPY a.txt /b + b.txt c.txt /y
COPY /b a.txt + b.txt c.txt /y

注意:为了进一步混淆,在源文件之后添加/ b会将/ b应用于之后的每个源文件,直到出现/ a。

在正常操作中,此行为看起来似乎很奇怪。由于DOS文件系统始终记录文件大小,因此文件结尾字符应该是多余的。

https://en.wikipedia.org/wiki/End-of-file

这样做有两个原因:

与CP / M的向后兼容性。 CP / M文件系统仅以128字节“记录”的倍数记录文件的长度,因此 按照惯例,Control-Z字符用于标记 有意义的数据(如果它在记录中间结束)。 MS-DOS 文件系统始终记录文件的确切字节长度,因此这 在MS-DOS上根本不需要。

它允许程序使用相同的代码从终端和文本文件中读取输入。

其结果是,它允许人们从设备(例如COM端口)获取输入或输出到设备,同时仍然能够区分不同的文件。

https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/copy

您可以用设备名称代替一个或多个出现的源或目的地。