1

I need to count the number of lines and columns that several files have. So far I managed to get the number of rows

@echo off
if exist counts.txt del counts.txt
for /R "path To folder" %%a in (*.txt) do call :sub %%a
goto :eof

:Sub
for /F %%c in ('type "%*" ^| find /c /v ""') do set rowCount=%%c
echo %*;%rowCount% >> counts.txt

This batch file saves file name and row count separated by ;. What I got stuck with is the column count. Any idea?

Possibly the output will be

file path;row count;col count

Michele
  • 8,563
  • 6
  • 45
  • 72
  • Are you trying to count the columns in csv files? Or are you looking for the maximum length of a row in each file, 1 character = 1 column? – rojo Jan 29 '15 at 16:30
  • columns in csv file, assuming comma as a delimiter. (so count of them plus 1) – Michele Jan 29 '15 at 16:47

1 Answers1

1

Solution 1:

A basic for loop evaluates unquoted commas, spaces, tabs, and semicolons as delimiters. The magic is that it'll correctly skip quoted commas. To count columns in your CSV file, you could just for %%I in (first line) do increment counter. This will only work if your csv header row does not contain unquoted spaces or other delimiters. If you prefer to follow your original logic and count the number of commas, then see solution #2 below.

@echo off
setlocal

if exist counts.txt del counts.txt
for /R "path To folder" %%a in (*.txt) do call :sub "%%~fa"
goto :eof

:Sub
setlocal
for /F %%c in ('type "%~1" ^| find /c /v ""') do set rowCount=%%c

:: read first line of file.txt into var
set /P "line=" <"%~1"

:: delayed expansion prevents evaluation of special characters
setlocal enabledelayedexpansion
set count=0
for %%I in (!line!) do set /a count += 1
endlocal & set "colCount=%count%"

:: If you want to echo only filename.ext to counts.txt, un-rem this and
:: use %filename% instead of %~1 in your echo. 
rem for %%I in ("%~1") do set "filename=%%~nxI"

echo %~1;%rowCount%;%colCount% >> counts.txt
endlocal

Solution 2:

Uses a :length function to get the length of the header row with and without commas, and returns the difference + 1. (:length function logic is based on jeb's :StringLength.) This will only work if your csv files have no header rows, or if the header rows are guaranteed not to contain quoted commas.

@echo off
setlocal

if exist counts.txt del counts.txt
for /R "path To folder" %%a in (*.txt) do call :sub "%%~fa"
goto :eof

:Sub
setlocal
for /F %%c in ('type "%~1" ^| find /c /v ""') do set rowCount=%%c

:: read first line of file.txt into var
set /P "line=" <"%~1"
set colCount=0

:: delayed expansion prevents evaluation of special characters
setlocal enabledelayedexpansion
set line=!line:"=!
call :length b4 "!line!"
call :length after "!line:,=!"
endlocal & set /a colCount = %b4% - %after% + 1

:: If you want to echo only filename.ext to counts.txt, un-rem this and
:: use %filename% instead of %~1 in your echo.  
rem for %%I in ("%~1") do set "filename=%%~nxI"

echo %~1;%rowCount%;%colCount% >> counts.txt
echo %~1;%rowCount%;%colCount%
endlocal
goto :EOF

:length <return_var> <string>
setlocal enabledelayedexpansion
set "tmpstr=%~2"
set ret=0
for %%I in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
    if not "!tmpstr:~%%I,1!"=="" (
        set /a "ret += %%I"
        set "tmpstr=!tmpstr:~%%I!"
    )
)
endlocal & set "%~1=%ret%"
goto :EOF
Community
  • 1
  • 1
rojo
  • 24,000
  • 5
  • 55
  • 101