Create a set of folders with cmd - Set a loop variable with a space

Viewed 119

I don't know if its age or lack of practice. Either way I cannot wrap my head around this issue. I am trying to set a subroutine but the string that I am passing along are being split because of the space in string 3 and 4.

SET SubA=String1,String2,String 3,String 4
FOR %%A IN (%SubA%) DO MD "%%A"

I've tried parenthesis around the string The <> brackets like Microsoft says to use. I have also tried this line below without success.

setlocal enableDelayedExpansion
For /F "tokens=* delims=" %%A  IN (%Var%) DO  MD "%%A"

Also I would love if possible could I make an list, possibly with an array. Like in Power shell I could do this. I really need to keep in the same batch file so the user could edit the list. I am aware that I could use caret but the easier I can make it for my client the better.

$Folders (
String1
String2
String 3
String 4
)

Edit: My desired result is to have this script create a set of folders like those pictured. Desired Results

3 Answers

The simplest pure batch-file solution that doesn't require trickery is to use for's ability to enumerate space-separated tokens.

For this to work as intended, tokens that themselves contain spaces must be double-quoted:

@echo off & setlocal

:: Space-separated list of folder names, with names that contains
:: spaces themselves double-quoted.
SET SubA=String1 String2 "String 3" "String 4"

:: Loop over the list elements and create a directory for each.
FOR %%A IN (%SubA%) DO MD %%A

As Compo's helpful answer implies, you could actually pass this list to a single invocation of
MD: MD %SubA%


Unfortunately, as far as I know, batch files do not offer a convenient way to define lists in a one-item-per-line format.

However, you could provide the list of names via an external file, with each name on its own line (no double-quoting needed), which can then be parsed with for /f; e.g.:

@echo off & setlocal

:: Determine the full path of the file "names.txt" 
:: located in the same folder as this batch file.
set "nameList=%~dp0names.txt"

:: Loop over all names in the file and call `md` with each.
for /f "usebackq delims=" %%n in ("%nameList%") do md "%%n"

And input file names.txt would then contain something like:

String1
String2
String 3
String 4

The simplest way to 'make' your directories is probably like this:

Set "SubA=String1,String2,String 3,String 4"
MD "%SubA:,=" "%" 2>NUL

As for working with the initial variable, and using it array like, you could do it like this:

@Echo Off & SetLocal EnableExtensions EnableDelayedExpansion

Set "SubA=String1,String2,String 3,String 4"

For /F "Delims==" %%G In ('"(Set Index[) 2>NUL"') Do Set "%%G="
Set "i=0"
Set "Index[!i!]=%SubA:,=" & Set /A i += 1 & Set "Index[!i!]=%"
(Set Index[) 2>NUL && Pause

Or you could do it like this:

@Echo Off & SetLocal EnableExtensions EnableDelayedExpansion

Set "SubA=String1,String2,String 3,String 4"

For /F "Delims==" %%G In ('"(Set Index[) 2>NUL"') Do Set "%%G="
Set "i=-1"
For %%G In ("%SubA:,=","%") Do (Set /A i += 1
    Set "Index[!i!]=%%~G")
(Set Index[) 2>NUL && Pause

Here is another way to create the directories using the PowerShell that is already on your system if it is still supported by Microsoft. When you are satisfied that the correct directories will be created, remove the -WhatIf from the mkdir command.

SET "SubA=String1,String2,String 3,String 4"
powershell -NoLogo -NoProfile -Command ^
    "'%SubA%'.split(',') | ForEach-Object { mkdir $_ -WhatIf | Out-Null }

A better way would be to test to see if the directory already exists before trying to create it.

SET "SubA=String1,String2,String 3,String 4"
powershell -NoLogo -NoProfile -Command ^
    "'%SubA%'.split(',') | ForEach-Object {" ^
        "if (-not (Test-Path -Path $_)) { mkdir $_ | Out-Null }" ^
    "}"
Related