W jaki sposób plik wsadowy może za każdym razem zastępować zawartość wyjściową?

0

Mam poniżej ten plik wsadowy, który jest prostą emulacją headpolecenia Unixa - odczyta pierwsze COUNT wiersze z wejściowego pliku .csv (nazwanego jako parametr wiersza polecenia). Jednak w przeciwieństwie do polecenia Unix, zapisuje do zakodowanego pliku wyjściowego. Jedynym problemem jest teraz to, że ten plik wsadowy zostanie kilkakrotnie wywołany w celu utworzenia tego pliku wyjściowego i będzie nadal dołączał wyniki do pliku wyjściowego. Nie mogę zmienić >>się >, ponieważ jest to forpętla i po prostu zachować zastąpieniem jednej linii do mojego pliku wyjściowego, który jest nieprawidłowy. Czy ktoś ma jakieś pomysły, jak zastąpić wyjściowy plik .csv przy każdym uruchomieniu pliku wsadowego?

@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
batchnoober
źródło

Odpowiedzi:

3

Zamiast usuwać plik, osobiście wolałbym zastąpić plik „nic”:

type NUL>trimmed.csv

Umieść go gdzieś nad pętlą.

Spowoduje to utworzenie pustego pliku lub zastąpienie istniejącego pliku pustym plikiem o nazwie trimmed.csv. Ponieważ nadpisuje, a nie usuwa i nie tworzy ponownie, powinien zachować datę utworzenia oryginalnego pliku.

Kok
źródło
To jest dobre. Właściwie to pomyślałem o jego usunięciu, ale jest to lepsza opcja.
batchnoober
4

Być może po prostu usuń go na początku partii (lub na górze sekcji: print_head)?

Coś jak del trimmed.csv /Q.

W ten sposób jest usuwany przy następnym uruchomieniu, ale nadal jest tworzony i dołączany podczas działania pętli.

Ƭᴇcʜιᴇ007
źródło
0

Wiem, że to stare pytanie; Ponieważ jednak nie widziałem tej potencjalnej odpowiedzi, dodaję ją jednak, ponieważ może to być lepsza odpowiedź dla niektórych osób ...

Zamiast po prostu:

@echo>>trimmed.csv %%a

Który, jak wspomniano, po prostu doda istniejący plik wyjściowy, spróbuj użyć:

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

W ten sposób nie musisz się martwić o sprawdzenie, czy plik istnieje i usunięcie go, jeśli tak jest. Dodatkowo, w pierwszym wierszu danych wyjściowych automatycznie zastępuje istniejący plik jako nowy pusty plik lub uruchamia nowy plik, jeśli nie, a następnie dołącza resztę wierszy.

Chociaż osobiście prawdopodobnie użyłbym sformatowanej daty dołączonej lub dołączonej do pliku basename (tj. 2018-11-17_trimmed.csv lub trimmed_2018-11-17.csv) przy użyciu danych wyjściowych polecenia „data” wypchanych do zmiennej ( aby „data” nie była uruchamiana dla każdej iteracji pętli).

Mce128
źródło
0

Oto (IMO) prostszy, bardziej bezpośredni sposób: umieść całą forpętlę w nawiasach i przenieś przekierowanie We / Wy poza nawiasy -  >zamiast  >>:

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

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

Tak więc, gdy pętla jest uruchamiana, plik jest otwierany do zapisu (czyszczenie poprzedniej zawartości, jeśli plik już istnieje / nadal istnieje). Plik wsadowy utrzymuje następnie plik CSV otwarty jako standardowe wyjście przez cały czas trwania pętli, więc wszystko, co zapisano na standardowe wyjście z pętli, przejdzie do pliku CSV.

Może to być nawet nieskończenie wydajniejsze niż oryginalna wersja pliku wsadowego, ponieważ ten (potencjalnie) musi otwierać i zamykać plik wyjściowy COUNT razy, podczas gdy moja wersja musi to zrobić tylko raz.

Scott
źródło