批处理文件如何每次都覆盖输出内容?

批处理文件如何每次都覆盖输出内容?

我有下面这个批处理文件,它是 Unix 命令的简单模拟head——它将读取第一个数数来自输入 .csv 文件的行(以命令行参数命名)。但是,与 Unix 命令不同,它会写入硬编码的输出文件。现在唯一的问题是,这个批处理文件将被多次调用来创建这个输出文件,并将继续将结果附加到输出文件中。我无法更改 to,>>因为>这是一个for循环,只会继续将一行覆盖到我的输出文件中,这是不正确的。有人知道如何在每次运行批处理文件时覆盖输出 .csv 文件吗?

@echo off

if [%1] == [] goto usage
if [%2] == [] goto usage

call :print_head %1 %2
goto :eof

REM
REM print_head
REM Prints the first non-blank %1 lines in the file %2.
REM
:print_head
setlocal EnableDelayedExpansion
set /a counter=0

for /f ^"usebackq^ eol^=^

^ delims^=^" %%a in (%2) do (
        if "!counter!"=="%1" goto :eof
        @echo>>trimmed.csv %%a
        set /a counter+=1
)

goto :eof

:usage
echo Usage: head.bat COUNT FILENAME

答案1

我个人更愿意用“无内容”覆盖该文件,而不是删除该文件:

type NUL>trimmed.csv

将其放置在环上方的某个位置。

这将创建一个空白文件,或用名为 的空文件覆盖现有文件trimmed.csv。由于这是覆盖,而不是删除并重新创建,因此它应该保留原始文件的创建日期。

答案2

也许只是在批次开始时(或在:print_head 部分的顶部)将其删除?

就像是del trimmed.csv /Q

这样,它会在下次运行时被删除,但在循环运行时仍会被创建并附加。

答案3

我知道这是一个老问题;然而,因为我没有看到这个潜在的答案,所以我还是添加它了,因为它可能是某些人的首选答案......

而不仅仅是:

@echo>>trimmed.csv %%a

如上所述,它只会附加现有的输出文件,请尝试使用:

if [[ "$counter" -eq 0 ]]; then 
    @echo > trimmed.csv %%a
else
    @echo >> trimmed.csv %%a        
fi

这样,您就不必担心检查文件是否存在,如果存在则删除它。此外,在输出的第一行,它会自动将现有文件覆盖为新的空文件,如果不存在则启动一个新文件,然后它会附加其余行。

但是,就我个人而言,我可能会使用一些格式化的日期附加或添加到文件基名(即 2018-11-17_trimmed.csv 或 trimmed_2018-11-17.csv)并使用“date”命令的输出填充到变量中(这样“date”就不会在每次循环迭代中运行),甚至两者兼而有之。

答案4

这是一个(在我看来)更简单、更直接的方法:将整个for循环放在括号中,并将 I/O 重定向移到括号外 — 而 >不是 >>

(
    for /f ^"usebackq^ eol^=^

    ^ delims^=^" %%a in (%2) do (
            if "!counter!"=="%1" goto :eof
            @echo %%a
            set /a counter+=1
    )
) > trimmed.csv

因此,当循环开始时,文件将打开进行写入(如果文件已经存在/仍然存在,则破坏先前的内容)。然后,批处理文件将在整个循环期间将 CSV 文件保持打开作为标准输出,因此从循环内部写入标准输出的任何内容都将进入 CSV 文件。

这甚至可能比批处理文件的原始版本效率更高,因为那个(可能)必须打开和关闭输出文件数数次,而我的版本只需要执行一次。

相关内容