I have this .bat file that I use to open .csv files, which counts the lines in them and uses Excel to open if under a million records and a separate program to open if more than a million records. The issue I'm running into is that if the file has more than ~ five million records it seems like the .bat takes a long time to count them before opening in the second program (sometimes ~10 seconds) and that kind of defeats the purpose of having this script to intelligently choose which program to use. The code I'm currently using is:

set LINE_COUNT=0

for /f %%a in ('type "%CSV_FILE%" ^| find /c /v ""') do set LINE_COUNT=%%a

If there's a faster way to do this I'm all ears.

I tried using a filesize threshold, first but sometimes the data structure has a far greater number of fields than records, so I'll have a large file size with less than a million records and don't want those opening in the second program.

4 Replies 4

find /c /v "" "%CSV_FILE%"

returns something like (note a space before displayed count of lines)

---------- expanded_variable_CSV_FILE: 23

Hence, following code snippet should do the trick:

for /f "delims=" %%G in ('find /c /v "" "%CSV_FILE%"') do (
    for %%a in (%%~G) do set /a "LINE_COUNT=%%a"
)

Here

  • %%G loop grabs output from the find command, and
  • %%a loop gets the last token in that string…

Simpler: for /f "tokens=2 delims=:" %%G in ('find /c /v "" "%CSV_FILE%"') do set /a "LINE_COUNT=%%G"

As an extension of the already offered methodology, you can reduce the output from the 'find' utility to just the number of lines by using the standard input redirector. You can also slightly speed up the command itelf by using the full path and extension for the 'find' utility:

Example:

%SystemRoot%\System32\find.exe /C /V "" 0<"%CSV_FILE%"

I suppose therefore you could do it like this:

If Exist "%CSV_FILE%" (
    For /F %%G In (
        '%SystemRoot%\System32\find.exe /C /V "" 0^<"%CSV_FILE%" 2^>NUL'
    ) Do If %%G LEq 1000000 (
        Start "" "%ProgramFiles%\Microsoft Office\root\Office16\EXCEL.EXE" "%CSV_FILE%"
    ) Else Start "" "%ProgramFiles%\Another Application\MyProgramName.exe" "%CSV_FILE%"
)

Below is my code for counting the number of lines in a file. Strictly speaking, it counts LFs:


@echo off & setLocal enableExtensions disableDelayedExpansion
(call;) %= sets errorLevel to 0 =%

call :countLines noOfLines "%~1" || goto die
echo(file "%~nx1" has %noOfLines% line(s)
goto end

:die
(call) %= sets errorlevel to 1 =%

:end
endlocal & goto :EOF

:countLines result= "%file%"
:: counts the number of lines in a file
setLocal
(call) %= error flag stays up if for loop fails =%

for /f "delims=:" %%N in ('
    cmd.exe /d /a /c type "%~2" ^^^& ^<nul set /p "=#" ^| (^
    2^>nul findStr.exe /n "^" ^&^& echo(^) ^| ^
    findStr.exe /blv 1: ^| 2^>nul findStr.exe /lnxc:" "
') do (endlocal & set "%1=%%N" & call;) %= for /f =%

exit /b %= countLines =%

The routine has the following features:

  • counts beyond the Batch 2Gb limit
  • handles long lines
  • processes Unicode or ANSI text files
  • no temporary files
  • fast on large files

Error checking is rudimentary, but functional.

Your Reply

By clicking “Post Your Reply”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.