У меня есть этот пакетный файл ниже, который является простой эмуляцией команды head Unix - он будет читать первые строки COUNT из входного файла .csv (названного параметром командной строки). Однако, в отличие от команды Unix, она записывает в жестко закодированный выходной файл. Единственная проблема сейчас заключается в том, что этот пакетный файл будет вызываться несколько раз для создания этого выходного файла и будет продолжать добавлять результаты в выходной файл. Я не могу изменить >> на > так как это цикл 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

4 ответа4

4

Возможно, просто удалите его в начале пакета (или в верхней части раздела:print_head)?

Что-то вроде del trimmed.csv /Q

Таким образом, он удаляется при следующем запуске, но все равно создается и добавляется, пока выполняется цикл.

3

Вместо того, чтобы удалять файл, я лично предпочел бы перезаписать файл «ничем»:

type NUL>trimmed.csv

Поместите это где-нибудь выше петли.

Это создает пустой файл или перезаписывает существующий файл с пустым файлом с именем trimmed.csv . Поскольку он перезаписывает, а не удаляет и воссоздает, он должен сохранять первоначальную дату создания файла.

0

Я знаю, что это старый вопрос; Однако, так как я не видел этот потенциальный ответ, я все же добавляю его, так как он может быть предпочтительным ответом для некоторых людей ...

Вместо просто:

@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, вставленные в переменную ( так что «дата» не выполняется для каждой итерации цикла.) или даже делать оба.

0

Вот более простой (IMO) способ: поместите весь цикл for в круглые скобки и переместите перенаправление ввода / вывода за пределы круглых скобок - с помощью > вместо >>:

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

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

Таким образом, когда цикл запускается, файл открывается для записи (забивая предыдущее содержимое, если файл уже существует).  Пакетный файл затем сохраняет CSV-файл открытым в качестве стандартного вывода в течение всей продолжительности цикла, поэтому все, что записано в стандартный вывод из цикла, попадет в файл CSV.

Это может быть даже намного более эффективным, чем исходная версия командного файла, потому что этот (потенциально) должен открывать и закрывать выходной файл COUNT раз, в то время как моя версия должна делать это только один раз.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .