Convert configuration file into variables and convert forward slash to backslash - batch-file

I have a configuration file which I need for my bash script which has a layout:
A=C:/Example1/A
B=C:/Example2/B
C=C:/Example3/C
I want to use the same configuration file for my windows batch file. I need to convert the above file into variables which I have done using:
for /f "delims=" %%x in (test.txt) do (set "%%x")
How do I go about converting this file into variables while also converting all the forward slashes into backslashes?
Thanks!

add after your for line,
for /f "delims==" %%x in (q888.txt) do call set "%%x=%%%%x:/=\%%"
or, as a replacement for your existing for,
for /f "tokens=1*delims==" %%x in (q888.txt) do set "%%x=%%y"&call set "%%x=%%%%x:/=\%%"
(I used a file called q888.txt for testing)
The first smply executes a substitution, using a parsing trick. The second combines the set and substitution into one cascaded command by tokenising on = into %%x and %%y

This could be done with the following batch code:
#echo off
if not exist "test.txt" goto :EOF
setlocal EnableDelayedExpansion
for /F "usebackq tokens=1* delims==" %%I in ("test.txt") do (
if not "%%~J" == "" (
set "Value=%%~J"
set "Value=!Value:/=\!"
set "_%~n0_%%~I=!Value!"
)
)
echo The variables set from file are:
echo/
set "_%~n0_"
echo/
pause
endlocal
The batch file first checks if the file to process exists in current directory at all. The batch file processing is exited with a jump to predefined label EOF (end of file, requires enabled extensions which are enabled by default) in case of the file test.txt does not exist at all.
Next the file is read line by line with skipping empty lines and lines starting with a semicolon by command FOR which splits each line up into two strings.
The first string left of first equal sign is assigned to loop variable I. Everything right of first equal sign is assigned next loop variable J according to ASCII table.
The IF condition in the loop checks if a value is also defined for a variable. The value is assigned to an environment variable on which a string substitution is executed using delayed expansion to replace all / by \.
Then the modified value is assigned to an environment variable with a name starting with _, the name of the batch file, one more underscore and the string assigned to loop variable I read from the file.
For demonstration the variables with their values are finally output before the local variables are discarded on execution of last command ENDLOCAL.
I strongly recommend not assigning the values read from the file directly to environment variables whose name is completely also read from the file as this makes the batch file easy to manipulate by just modifying the contents of the text file. For example path=C:\Temp in text file would otherwise result in set "Path=C:\Temp" and from this point of batch file execution the running Windows command process would not find anymore any standard executable in directories defined by default in environment variable PATH like %SystemRoot%\System32.
A second variant which incorporates answer posted by Magoo with above batch code:
#echo off
if not exist "test.txt" goto :EOF
setlocal DisableDelayedExpansion
for /F "usebackq tokens=1* delims==" %%I in ("test.txt") do if not "%%~J" == "" set "_%~n0_%%~I=%%~J" & call set "_%~n0_%%~I=%%_%~n0_%%~I:/=\%%"
echo The variables set from file are:
echo/
set "_%~n0_"
echo/
pause
endlocal
The advantage of this variant is that delayed expansion is not needed for this solution which makes it possible to correct process also lines from file containing 1 or more exclamation marks on which first variant fails. And it is also a little bit faster, not noticeable faster for a human, but nevertheless a bit faster.
In both batch code blocks _%~n0_ can be replaced by (nearly) anything including also nothing although that is not recommended. Using just an underscore would be also possible as there are no environment variables defined by default by Windows which start with an underscore.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /? ... explains %~n0 (name of argument 0 - the batch file name - without path and without file extension).
echo /?
endlocal /?
for /?
goto /?
if /?
pause /?
set /?
setlocal /?

The simplest solution is to let the ~f FOR variable modifier put the full path in canonical form (including conversion of forward slashes to back slashes). I use the DELIMS and TOKENS options to split each line into the variable name and path so that I can apply the ~f to the path. It is important to use tokens=1* instead of tokens=1,2 just in case the path includes a = character.
for /f "delims== tokens=1*" %%A in (test.txt) do (set "%%A=%%~fB")
Note, however, that this strategy only works if your "test.txt" already contains full, absolute paths. If the file contains relative paths, then the ~f modifier will add drive and or folder values from the current directory to turn the relative path into an absolute path.

Related

What is the reason for error message "N was unexpected at this time"?

File: stack.bat
#echo off
#setlocal enabledelayedexpansion
for %%a in (%*) do (
call set "%%~1=%%~2"
shift
)
ECHO para1 %--para1%
ECHO para2 %--para2%
if "%--para2%"=="" (
echo missing para2
for /f "eol=: delims=" %F in ('dir /b/o:N %--folder%\*.001') do #set "newest=%F"
echo latest %newest%
)
This batch file is called with:
stack.bat --para1 c:\Sample\temp
The execution results in output of the error message:
N was unexpected at this time.
There is no error if the line for /f "eol=: ... is commented out with command REM.
Delayed expansion is already enabled.
What do I need to do to fix the error?
It is not described what the batch file code should do at all. It looks like it should find the newest file by its name containing most likely a date string in name in a directory passed as argument to the batch file and should define an environment variable with name passed also as argument left to the directory path with the file name of newest file.
I suggest following commented batch code for this purpose:
#echo off
rem Remove this line if the environment variables defined by this batch
rem file should still exist after processing of this batch file finished.
setlocal EnableExtensions DisableDelayedExpansion
rem Delete all environment variables of which name starts with --.
for /F "delims=" %%I in ('set -- 2^>nul') do set "%%I"
:ProcessArguments
rem Get current first argument (option) with surrounding " removed.
set "Option=%~1"
rem Is there no more option?
if not defined Option goto EndBatch
rem Remove all double quotes from the option.
set "Option=%Option:"=%"
rem This condition is just for 100% fail safe code. It should be never true.
if not defined Option goto EndBatch
rem Does the option not start with two hyphens?
if not "%Option:~0,2%" == "--" (
echo ERROR: Invalid option: "%Option%"
echo/
goto EndBatch
)
rem Get current second argument (folder path) with surrounding " removed.
set "Folder=%~2"
rem Is there no folder path?
if not defined Folder goto MissingFolder
rem Remove all double quotes from the folder path.
set "Folder=%Folder:"=%"
rem This condition is just for 100% fail safe code. It should be never true.
if not defined Folder goto MissingFolder
rem Replace all / in folder path by \ as many users type folder paths wrong
rem with slashes as on Linux/Mac instead of backslashes as required on Windows.
set "Folder=%Folder:/=\%"
rem Make sure the last character of folder path is a backslash.
if not "%Folder:~-1%" == "\" set "Folder=%Folder%\"
rem Search in specified folder for *.001 files output reverse by name and
rem define the option as environment variable with first output file name
rem assigned with full qualified absolute path even if environment variable
rem Folder referencing a relative path. Then shift the arguments list by
rem two arguments to the left and process the remaining arguments.
for /F "eol=| delims=" %%I in ('dir "%Folder%*.001" /A-D /B /O-N 2^>nul') do (
for %%J in ("%Folder%%%I") do set "%Option%=%%~fJ"
shift
shift
goto ProcessArguments
)
rem It is not possible to define an environment variable with no string.
rem So an error message is output if no file could be found like on
rem wrong folder path or no *.001 file found in the specified folder.
echo ERROR: Could not find a *.001 file for option "%Option%" in folder:
echo "%Folder%"
echo/
goto Endbatch
:MissingFolder
echo ERROR: Missing folder path for option: "%Option%"
echo/
:EndBatch
set "Option="
set "Folder="
echo Options parsed successfully:
echo/
set -- 2>nul
rem Remove this line if the environment variables defined by this batch
rem file should still exist after processing of this batch file finished.
endlocal
This batch file can be started for example with the command line:
stack.bat --para1 c:\Sample\temp "--para2" "C:/Temp/Development & Test!/" --para3 . --para4 "\Program Files\Internet Explorer\" -para5 .."
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /? ... explains how to reference batch file arguments
dir /?
echo /?
endlocal /?
for /?
goto /?
if /?
rem /?
set /?
setlocal /?
shift /?
Read the Microsoft documentation about Using command redirection operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir command line with using a separate command process started in background with %ComSpec% /c and the command line within ' appended as additional arguments.
I suggest also reading:
How does the Windows Command Interpreter (CMD.EXE) parse scripts?
This question with its answers should be read first by every beginner in batch file coding.
Problems checking if string is quoted and adding quotes to string
This answer explains very detailed how to process arguments passed to a batch file.
Syntax error in one of two almost-identical batch scripts: ")" cannot be processed syntactically here
This answer describes common issues made by beginners in batch file coding and how to avoid them.
Why is no string output with 'echo %var%' after using 'set var = text' on command line?
Another extensive answer which describes how to work with environment variables in batch files.
Symbol equivalent to NEQ, LSS, GTR, etc. in Windows batch files
This also very long answer describes in detail how a string comparison is done by Windows command processor and what a batch file writer must take into account on using string comparisons.

Get directory name from array in Batch [duplicate]

This question already has answers here:
Arrays, linked lists and other data structures in cmd.exe (batch) script
(11 answers)
Closed 3 years ago.
I have a list of paths from which I want to extract folder name
I wrote:
#echo off
set paths[0]="C:\p\test1"
set paths[1]="C:\p\test2"
set paths[2]="C:\p\test3"
(for %%p in (%paths%) do (
for %%F in (%%p) do echo Processing %%~nxF
))
but seems that nothing is shown.
I expected to see:
Processing test1
Processing test2
Processing test3
It makes a big difference if first " is specified on a set command line left to variable name or left to variable value. In most cases it is better to specify it left to the variable name, especially if a variable value holding a path should be concatenated later with a file name to a full qualified file name.
See also: Why is no string output with 'echo %var%' after using 'set var = text' on command line?
The solution for this task is:
#echo off
set "paths[0]=C:\p\test1"
set "paths[1]=C:\p\test2"
set "paths[2]=C:\p\test3"
for /F "tokens=1* delims==" %%I in ('set paths[ 2^>nul') do echo Processing %%~nxJ
The command FOR with option /F and a set enclosed in ' results in starting one more command process running in background with %ComSpec% /c and the command line specified between the two ' appended as further arguments. So executed is in this case with Windows installed to C:\Windows:
C:\Windows\System32\cmd.exe /c set paths[ 2>nul
The command SET outputs all environment variables of which name starts with paths[ line by line using the format VariableName=VariableValue to handle STDOUT of started background command process.
It could be that there is no environment variable of which name starts with paths[ which would result in an error message output to handle STDERR by command SET which would be redirected from background command process to handle STDERR of the command process which is processing the batch file and for that reason would be displayed in console window. For that reason a possible error message is redirected by the background command process to device NUL to suppress it with using 2>nul.
Read the Microsoft article about Using command redirection operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded set command line with using a separate command process started in background.
FOR captures in this case everything written to handle STDOUT of started background command process and process this output line by line after started cmd.exe terminated itself.
Empty lines are ignored by FOR which does not matter here as there are no empty lines to process.
FOR would split up a non-empty line into substrings using normal space and horizontal tab as string delimiters and would assign just first space/tab separated string to specified loop variable, if it does not start with default end of line character ;. This default line splitting behavior is not wanted here. For that reason the option delims== defines the equal sign as string delimiter.
The option tokens=1* instructs FOR to assign in this case the variable name to specified loop variable I and assign everything after the equal sign(s) after variable name without any further string splitting on equal signs to next loop variable according to ASCII table which is in this case J. That is the reason why loop variables are interpreted case-sensitive while environment variables are handled case-insensitive by the Windows command processor.
In this case only the variable value is of interest in the body of the FOR loop. For that reason just loop variable J is used on ECHO command line while I is not used at all.
The modifier %~nxJ results in removing surrounding double quotes from string value assigned to loop variable J and next get the string after last backslash or beginning of string in case of the string value does not contain a backslash at all. This is the name of the last folder in folder path string.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
echo /?
for /?
set /?
UPDATE:
There is a big advantage of this solution in comparison to the other two solutions posted up to now here:
There is not used delayed environment variable expansion which is always problematic on working with file or folder names on not being 100% sure that no folder and no file contains ever an exclamation mark in its name.
Let us compare the three solutions with unusual folder names containing !.
#echo off
rem Make sure there is no environment variable defined of which name starts with
rem paths[ as suggested by Compo which is a very valuable addition on my code.
for /F "delims==" %%I in ('set paths[ 2^>nul') do set "%%I="
set "paths[0]=C:\p\test1!"
set "paths[1]=C:\p\!test2"
set "paths[2]=C:\p\!test!3"
echo/
echo Results of solution 1:
echo/
for /F "tokens=1* delims==" %%I in ('set paths[ 2^>nul') do echo Processing %%~nxJ
echo/
echo Results of solution 2:
echo/
SetLocal EnableDelayedExpansion
for /L %%i in (0,1,2) do (
for %%j in (!paths[%%i]!) do echo Processing %%~nxj
)
endLocal
echo/
echo Results of solution 3:
echo/
Setlocal EnableDelayedExpansion
Call :process paths "!paths[0]!" "!paths[1]!" "!paths[2]!"
Endlocal
echo/
pause
goto :EOF
:process
Set P_C=0
Set /a P_C-=1
For %%a in (%*) DO (
CALL :populate %1 "%%~a"
)
Set /a P_C-=1
For /L %%b in (0,1,!P_C!) DO (
ECHO Processing %1[%%b] = "!%1[%%b]!"
)
GOTO :EOF
:populate
Set "%1[!P_C!]=%~2"
Set /a P_C+=1
GOTO :EOF
The output on running this batch file is:
Results of solution 1:
Processing test1!
Processing !test2
Processing !test!3
Results of solution 2:
Processing test1
Processing test2
Processing 3
Results of solution 3:
Processing paths[0] = "C:\p\test1\p\\p\3"
Solution 1 as posted here works for all three folder names correct.
Solution 2 omits for first and second folder name the exclamation mark which will most likely cause errors on further processing. The third folder name is modified to something completely different. Enabled delayed expansion results in parsing a second time echo Processing %%~nxj after %~nxj being replaced by !test!3 with interpreting test in folder name now as environment variable name of which value is referenced delayed. There was no environment variable test defined on running this batch file and so !test!3 became just 3 before echo was executed by Windows command processor.
Solution 3 produces garbage on any folder name contains an exclamation mark, even on full qualified folder name defined before enabling delayed expansion and referenced with delayed expansion on calling the subroutine process.
Well, folder and file names with an exclamation mark in name are fortunately rare which makes the usage of delayed expansion usually no problem. But I want to mention here nevertheless the potential problems which could occur on any folder name containing one or more !.
Something like that should work :
#echo off
set paths[0]="C:\p\test1"
set paths[1]="C:\p\test2"
set paths[2]="C:\p\test3"
SetLocal EnableDelayedExpansion
for /L %%i in (0,1,2) do (
for %%j in (!paths[%%i]!) do echo Processing %%~nxj
)
pause
Define the Array within the function.
This approach can be used to define multiplay Arrays.
#ECHO OFF
Setlocal EnableDelayedExpansion
:: REM P_C is used to define the range of the Array. The -1 operations on P_C is to shift the paths parameter out of the Arrays working Index.
::REM the first parameter passed is used as the Arrays Name. all other parameters are assigned to index values 0 +
Call :process paths "C:\p\test1" "C:\p\test2" "C:\p\test3"
pause
:process
Set P_C=0
Set /a P_C-=1
For %%a in (%*) DO (
CALL :populate %1 "%%~a"
)
Set /a P_C-=1
For /L %%b in (0,1,!P_C!) DO (
ECHO Processing %1[%%b] = "!%1[%%b]!"
)
GOTO :EOF
:populate
Set "%1[!P_C!]=%~2"
Set /a P_C+=1
GOTO :EOF

How get specific word from the file using batch scripting?

I have a file of which the contents are as follows which are in consecutive lines,
VERSION=7.0.2
BUILD=03bbabbd5c0f
PRODUCT=splunk
PLATFORM=Windows-AMD64
From this I only want the VERSION. I tried using the following command:
FOR /F "usebackq tokens=1 eol=P" %G IN ("C:\ProgramFiles\SplunkUniversalForwarder\etc\splunk.version") DO echo %G
Involved eol=P because it doesn't bring out the last two lines, but I don't want the second line too. Can anyone help? Actually the main goal is to get only the version number not even the "VERSION=".
Simpler:
FOR /F "tokens=2 delims==" %G IN ('findstr "VERSION" "C:\ProgramFiles\SplunkUniversalForwarder\etc\splunk.version"') DO echo %G
Use findstr command to select the desired line, that may be at any position in the file...
Along the lines of my comment.
At the Command Prompt:
For /F "UseBackQ EOL=P Tokens=1* Delims==" %A In ("%ProgramFiles%\SplunkUniversalForwarder\etc\splunk.version") Do #Echo %B
As a batch file:
For /F "UseBackQ EOL=P Tokens=1* Delims==" %%A In ("%ProgramFiles%\SplunkUniversalForwarder\etc\splunk.version") Do #Echo %%B
In a batch file use this code:
#echo off
for /F "usebackq tokens=1* delims==" %%A in ("C:\Program Files\SplunkUniversalForwarder\etc\splunk.version") do if /I "%%~A" == "VERSION" if not "%%~B" == "" set "Version=%%~B" & goto HaveVersion
echo Error: Could not find VERSION= with a version string in file:
echo C:\Program Files\SplunkUniversalForwarder\etc\splunk.version
pause
goto :EOF
:HaveVersion
echo Version is: %Version%
pause
Please note the space in Program Files.
The command FOR with the used option /F reads the specified file line by line with skipping empty lines and lines starting with ; which is the default for eol (end of line) option.
The option usebackq is required to get the full qualified file name enclosed in double quotes interpreted as file name and not as string to process. The double quotes " around full qualified file name are required because of space character.
delims== redefines the delimiters for splitting the lines into substrings (tokens) from default space and horizontal tab to equal sign. So FOR splits now the lines using only = as delimiter character for the strings.
tokens=1* means that the first equal sign delimited substring should be assigned to loop variable A. And the rest of the line after the first equal sign(s) should be assigned without any further splitting to next loop variable according to ASCII table which is in this case the loop variable B. Now it should be also clear why loop variables are case-sensitive while environment variables are not case-sensitive. It makes a difference on what is the next loop variable if the specified loop variable is A or a.
On each loop run first a case-insensitive string comparison is made to check if the version string is at beginning of current line. If this first condition is true a second IF condition is used to verify that there is really a version string right to the equal sign in the file. If this second condition is also true the version string is assigned to environment variable Version and the loop is exited by continuing the batch file processing with a jump to the line below label HaveVersion. So the other lines in file are not further processed by FOR.
In general it is better to reference the environment variable ProgramFiles with %ProgramFiles% instead of using C:\Program Files as the standard program files directory for 64-bit applications on Windows x64 respectively for 32-bit applications on Windows x86 can be on any drive with any folder name. But the Windows WOW64 Implementation Details must be taken into account if the batch file should work on 32-bit Windows, on 64-bit Windows in 64-bit environment and on 64-bit Windows in 32-bit environment. See also Wikipedia article about Windows Environment Variables.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
echo /?
for /?
goto /?
if /?
pause /?
set /?
See also Single line with multiple commands using Windows batch file for an explanation of operator &.

Modify variable within loop of batch script

I am moving files based on their names to preset folders. I don't want to make new folders. So files should only be moved if the corresponding folder is existing already.
The file names all follow the same pattern: 1234_123456_AA_***********.(doc/pdf)
I have the following script below which works:
#echo on
for /r %%f in (*.*) do (
echo processing "%%f"
for /f "tokens=1-3 delims=_" %%a in ("%%~nxf") do (
move "%%f" C:\Users\xxxxxxxxx\Desktop\MOVEFILES\%%a_%%b_%%c\
)
)
pause
But the issue I am running into is that some of the files names have a '0' place holder in loop variable %%b, for example 1234_0123456_AA. But this file name should be interpreted like 1234_123456_AA and I want this file moved into the appropriate folder.
I have written this:
#echo on
SETLOCAL ENABLEDELAYEDEXPANSION
for /r %%f in (*.*) do (
for /f "tokens=1-3 delims=_" %%a in ("%%~nxf") do (
set z=%%b%
echo !z:~-6!
move "%%f" C:\Users\xxxxxxxxx\Desktop\MOVEFILES\%%a_%%z_%%c\
)
)
pause
I get the echo to remove the '0' place holder, but need to get that back into %%b in the file path of where the file should be moved to.
What to modify in code to get the desired behavior?
Use the following code with the corrections of JosefZ applied and some additional improvements:
#echo off
setlocal EnableDelayedExpansion
for /R %%F in (*_*_*.*) do (
for /F "tokens=1-3 delims=_" %%A in ("%%~nxF") do (
set "MiddlePart=%%B"
set "MiddlePart=!MiddlePart:~-6!"
if exist "%USERPROFILE%\Desktop\MOVEFILES\%%A_!MiddlePart!_%%C\*" (
move /Y "%%F" "%USERPROFILE%\Desktop\MOVEFILES\%%A_!MiddlePart!_%%C"
)
)
)
endlocal
pause
The improvements on code are explained below in details.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
echo /?
endlocal /?
if /?
move /?
set /?
setlocal /?
1. Search pattern
The first improvement is the pattern used in first FOR as only files should be moved with at least 2 underscores in file name. This pattern is still not the best one, but good enough for this task.
2. Loop variable
It is better to use loop variables in upper case to avoid problems with the modifiers.
For example using as loop variable %%f and using inside the loop %%~f to use the string (must not be a file or folder name) of loop variable f without surrounding quotes, command processor exits batch processing with an error message because it expects one more letter, the loop variable as %%~f is interpreted as full name of file/folder of loop variable ?.
The loop variables and the modifiers are case sensitive. Therefore %%~F is interpreted by command processor as string of loop variable F without surrounding quotes and %%~fF as file/folder name with full path and extension of the file/folder of loop variable F.
Some other characters like # can be also used as loop variable.
3. Assigning value to environment variable with quotes
On assigning a string to an environment variable, it is always good to use
set "variable=text or other variable"
Using the quotes as shown here has the advantage that not visible spaces/tabs after last double quote are ignored by command processor.
But with using just
set variable=text or other variable
everything after first equal sign up to line termination is assigned to the variable including trailing spaces and tabs added perhaps by mistake on this line in the batch file. This is nearly never good and a common source of a batch execution problem which can be easily avoided by using quotes right.
Using the quotes as show below is also not good as in this case both double quotes are part of the text assigned to the variable (plus trailing spaces/tabs). This is sometimes useful, but is most often a coding mistake.
set variable="text or other variable"
4. Delayed expansion
Referencing a variable set or modified within a block defined with (...) requires delayed expansion if the current variable value should be used and not the value assigned to the variable above the block. Therefore using %%z was wrong in original code as variable z was not defined above first FOR loop and therefore was replaced always with nothing on execution of the loops.
5. Environment variable USERPROFILE
Running in a command prompt window set results in getting displayed all predefined environment variables for the current user account. There is the variable USERNAME, but also USERPROFILE containing path to the user´s profile directory with the Desktop folder and other user account related folders. Using environment variable USERPROFILE makes the batch file less dependent on Windows version and language of Windows.
ATTENTION:
The first FOR runs because of /R recursive on current directory and all its subdirectories. As the inner FOR loop moves all found files in current directory tree to subdirectories of %USERPROFILE%\Desktop\MOVEFILES, the current directory should be never any directory of this path.

Batch - Recurse directories from a variable and expand results in another variable

I'm creating a simple production environment for work and in doing so need to set specific environment variables for specific projects in batch file.
Here's what i want to achieve:
1) Define a single environment variable which would define a list of directories
2) Recurse down each directory and add all leaf folders to a final environment variable.
[EDIT] After looking back at what i originally posted i was able to remove some redundancy. But the "The input line is too long." error occurs when %LINE% gets too long. Using the short path expansion does help but it can still error out. I'll look at how to break the echo to a temp file next as suggested.
Here's what i currently have:
#echo off
set RECURSE_THESE_DIRS=C:\Users\eric\Autodesk
set TMP_FILE=%CD%TMP_FILE.%RANDOM%.txt
setLocal EnableDelayedExpansion
for %%i in (%RECURSE_THESE_DIRS%) do (
if exist %%~si\NUL (
for /f "tokens=*" %%G in ('dir /b /s /a:d %%i') do set LIST=!LIST!;%%G
)
)
set LIST=%LIST:~1%
rem !!! AT THE ECHO LINE BELOW IF %LIST% IS TOO LONG, THIS SCRIPT FAILS
rem !!! WITH The input line is too long. ERROR :(
echo %LIST%>%TMP_FILE%
endlocal
for /F "delims=" %%G in (%TMP_FILE%) do set FINAL_VAR=%%G
del /F %TMP_FILE%
So by setting RECURSE_THESE_DIRS to directories i wish to parse, i end up with a %FINAL_VAR% which i can use to specify paths for proprietary software i use. Or i could use this script to append to %PATH%, etc...
This works for me but i would love suggestions to improve/streamline my script?
The root of your problem is that batch is limited to fit the variable name, contents and = into 8192 bytes, hence your directory-list simply isn't going to fit into one variable.
Personally, I'd just spit out a dir/s/b/a-d list to a tempfile and process that file with a for/f "delims=" - after all, you'd be likely to need to process your ;-separated envvar similarly in whatever process you are proposing to execute.
For instance, here's a test producing the same error - not using filenames at all
#ECHO OFF
SETLOCAL
SET "var=hello!1234"
SET var=%var%%var%%var%%var%%var%
SET var=%var%%var%%var%%var%%var%%var%%var%%var%
SET var=%var%%var%%var%%var%%var%
SET var=%var%%var%%var%%var%
SET count=8000
:loop
SET /a count +=1
ECHO %count%
SET var=%var%x
ECHO %var%
GOTO loop
GOTO :EOF
This should fail where count=8184.
Suggestions:
Use for /d /r to handle the recursion
Maybe i'm wrong, but in your script, you traverse the directory hierarchy, adding each directory to temp file which is then readed to concatenate its lines into a variable which is then writed to temp file, to be read again in another variable. If concatenation of directories fit into a variable, why not concatenate them without any temporary file?
If concatenation is in the limit of line length, as suggested by npocmaka, and if soported by end application, user short paths. Also, instead of adding the new values in the same instruction (not line) that contains the for loop, use a call to a subrutine with the new value passed to it, and then append the value. It's slower, but command lines executed will be shorter.

Resources