1

My Windows batch file is supposed to read file names and create a directory that is named according to the filename's 2nd to 5th letter:

for %%f in (.\*.txt) do (
set string=%%~nf
mkdir %string:~2,5%     
)

The value of 'string' is not updated though, i.e. it is the same in each step of the loop. How can I have it updated?

This is the cmd output:

>for %f in (.\*.txt) do (
set string=%~nf
 mkdir le3
)

>(
set string=file1
 mkdir le3
)

>(
set string=file2
 mkdir le3
)
A subdirectory or file le3 already exists.

>(
set string=file3
 mkdir le3
)
A subdirectory or file le3 already exists.
Joan
  • 33
  • 3
  • Try consulting the hundreds of articles on SO about `delayedexpansion`. Essentially, a `%var%` within a code block is replaced by the value of `var` when the block is parsed. To access the changing value within a block, you feed first to invoke `delayedexpansion` using a `setlocal enabledelayedexpansion` command, and then use `!var!` to access the dynamic value of the variable. – Magoo Sep 28 '16 at 05:31
  • Thank you for your reply. I consulted several sites, e.g. [link](http://stackoverflow.com/questions/6679907/how-do-setlocal-and-enabledelayedexpansion-work) and came up with 'SETLOCAL ENABLEDELAYEDEXPANSION for %%f in (.\*.txt) do ( set !string!=%%~nf mkdir !string:~2,5! )' - but the delayed expansion does not seem to work yet. Do you have any advice what's wrong? – Joan Sep 28 '16 at 08:05
  • `set !string!=%%~nf` should be `set string=%%~nf` - you intend to set the variable `string`, not the variable `current content of string` – Magoo Sep 28 '16 at 13:43

2 Answers2

1

The problem you're running into is because of %variable% expansion. The entire FOR statement (including up to the closing parenthesis) is one statement. When it is read, the command processor replaces the %string% variable with whatever string is set to before the SET inside executes. (Actually, you're getting the subset of string starting at the 2nd character and proceeding 5 characters, but that's not really important here. My guess is that you've got %string% set to "file3".)

Anyway, you can fix it by adding SETLOCAL ENABLEDELAYEDEXPANSION at the top and using syntax like !string! instead of %string% inside the FOR.

You could also move the processing of %string% outside of FOR.

Look up HELP SETLOCAL and HELP SET for more.

Also, if you hadn't noticed, you're not getting the second and fifth characters of the filename... As I mentioned, you're getting a substring of (up to) length 5, starting at character 2. Look up HELP SET for more.

geisterfurz007
  • 5,292
  • 5
  • 33
  • 54
soja
  • 1,587
  • 8
  • 8
  • I have now enabled delayed expansion and adapted the code: `SETLOCAL ENABLEDELAYEDEXPANSION for %%f in (.\*.txt) do ( set !string!=%%~nf mkdir !string:~2,5! )` I understand the idea, also tried setting the quotation marks in different places, but still I don't get the delayed expansion to work - Any ideas? – Joan Sep 28 '16 at 07:27
0

Nearly, you've got a couple of unnecessary exclamation marks in your last attempt:

SETLOCAL ENABLEDELAYEDEXPANSION
for %%f in (*.txt) do (
    set string=%%~nf
    if not exist "!string:~2,5!\" mkdir "!string:~2,5!"
)
Compo
  • 36,585
  • 5
  • 27
  • 39