0

I am writing a script to iterate through all files in a folder using a batch script. The command I am using is

for /r F:\foo\ %%i in (bar_*.txt) do echo %%i

This works just fine. But if I substitute the %%i with %%files, I get an error which says %files was unexpected at this time. The documentation page says only single characters are allowed. What is the reason behind this? Is there any way through which I can give a more meaningful name to the variable?

mahacoder
  • 895
  • 3
  • 14
  • 29
  • 2
    The reason for the single-letter-variable: `for` is programmed that way. More meaningful name: no, but you can use a copy: `set files=%%i`. To use it, you need [delayed expansion](http://stackoverflow.com/a/30284028/2152082): `echo !file!` – Stephan May 16 '16 at 11:20
  • 1
    on of the reasons are [the consecutive tokens](http://ss64.com/nt/for_f.html) `if for /f`. In this case for command splits the i'ts output on tokens and to access the next one you need to use the next letter in the alphabet.Which would be not possible with words. – npocmaka May 16 '16 at 11:29
  • @Stephan your answer and the link solved multiple problems I had. The answer on delayed expansion is helpful and easy to understand – mahacoder May 16 '16 at 11:30

1 Answers1

0

Loop variables must be single character variables because of tokens=1,4,6-9 feature which would not be possible with loop variables with any name.

For example from CSV file input.csv the first data column, the fourth data column and the data columns six to nine should be written into CSV file output.csv.

@echo off
if not exist "input.csv" exit /B
if exist "output.csv" del "output.csv"
for /F "usebackq tokens=1,4,6-9 delims=," %%A in ("input.csv") do (
    echo %%A,%%B,%%C,%%D,%%E,%%F>>"output.csv"
)

Note 1: This works only if there are no empty field values in each data row.

Also it would be very difficult for Windows command processor to distinguish between referencing a loop variable and an environment variable if loop variables could have any name.

You can always assign value of a loop variable to an environment variable and use on the other command lines within the loop the environment variable using delayed expansion.

@echo off
setlocal EnableExtensions EnableDelayedExpansion
for /R F:\foo\ %%# in (bar_*.txt) do (
    set "FileName=%%#"
    echo Current file is: !FileName!
)
endlocal

Note 2: This works only for file names not containing ! in name or path.

Environment variables are not case-sensitive, but loop variables are case-sensitive. And avoid using letters for loop variables which could be interpreted also as modifiers for example on using %~nI, %~nxI or something similar as this could be problematic.

BTW: Why not using COPY with option /S or XCOPY or ROBOCOPY to copy recursively all files matching the wildcard pattern bar_*.txt?

Mofi
  • 46,139
  • 17
  • 80
  • 143