batch file blank variable - batch-file

I'm trying to rename the contents of a folder based on it's name and adding an alphabet at the end. But I'm having a hard time getting the letter based on my defined array of alphabets. Here's my code so far.
#echo off
set letters[1]=a
set letters[2]=b
set letters[3]=c
set letters[4]=d
set letters[5]=e
set letters[6]=f
set letters[7]=g
set letters[8]=h
set letters[9]=i
set letters[10]=j
set letters[11]=k
set letters[12]=l
set letters[13]=m
set letters[14]=n
set letters[15]=o
set letters[16]=p
set letters[17]=q
set letters[18]=r
set letters[19]=s
set letters[20]=t
set letters[21]=u
set letters[22]=v
set letters[23]=w
set letters[24]=x
set letters[25]=y
set letters[26]=z
set /a index=0
pushd %1
for %%a in (%1) do set folder=%%~na
echo renaming %folder%...
setlocal enabledelayedexpansion
for %%i in (*.*) do (
set /a index+=1
set suffix=!letters[%index%]!
echo appending -!suffix!...
ren "%%~fi" "%folder%-!suffix!.*"
)
endlocal
popd
pause
exit /b
I have read that using the EnableDelayedExpansion helps in these kinds of situation also the use of (!) for the delayed variable? I'm still pretty new at this, I don't know where am I going wrong with this or how I can create a work around for this. Thanks!

Replace the line
set suffix=!letters[%index%]!
with
CALL set suffix=%%letters[!index!]%%
%index% refers to the value of index at the time the for %%i is parsed, not as it changes through the operation of the loop.
Note that you'll run out of suffixes if you have more than 26 targets!
(btw - for %%a in (%1) do set folder=%%~na is probably better-off as set folder=%%~n1 )

Related

Defining a changing variable

I'm trying to create a variable that will link to others based off of a variable result, but can't seem to get it to work. Here's the code:
#echo off
set rollnumbera=10
set /a num=%random% %%rollnumbera +1
set "message=msg%num%"
set msg1=a
set msg2=b
set msg3=c
set msg4=d
set msg5=e
set msg6=f
set msg7=g
set msg8=h
set msg9=i
set msg10=j
echo %message%
echo %num%
pause
When I run it it displays the msg%num% result, but does not seem to be linking to the set msg#s. I'm wondering if there is a way to do that, or if an "if %num% == message number (echo message)" is required. This is just an ease of access question, but any advice would be appreciated.
The fixed code:
#echo off
setlocal enabledelayedexpansion
set rollnumbera=10
set /a num=(%random% %% rollnumbera)+1
set msg1=a
set msg2=b
set msg3=c
set msg4=d
set msg5=e
set msg6=f
set msg7=g
set msg8=h
set msg9=i
set msg10=j
for %%a in ("!msg%num%!") do set message=%%a
echo %message%
echo %num%
pause

Enter on a file, modify the rows and overwrite the file. With a .bat file

I am doing some modifications on a text file; however the program is adding lines instead of modifying them.
As i am new to it, can you help or guide me?
Here is my code:
setlocal enabledelayedexpansion
for /f "delims=" %%a in (economic_changes.txt) do (
SET s='%%a
SET s=!s:;= !
SET s=!s:- =-;;!
SET s=!s: -=-!
SET s=!s:-;;-=-;-!
SET s=!s:-=%!
SET s=!s:_= %!
SET s=!s:;=';'%!
SET s=!s:;'';'=;;%!
echo !s!
) >> "%userprofile%\desktop\Economic_Folder\economic_changes.txt"
Since the same file cannot be read and written at the same time, create a temporary file to store the changed lines into.
Several of the modifications have a SPACE character at the end. Using quotes makes it clear where those occur. Perhaps you want those. I do not know.
Then, of course, delete the temporary file once completed.
setlocal enabledelayedexpansion
SET "TMPFILE=%TEMP%\file_converter_%RANDOM%.tmp"
IF EXIST "%TMPFILE%" (DEL "%TMPFILE%")
for /f "delims=" %%a in (economic_changes.txt) do (
SET "s='%%a "
SET "s=!s:;= ! "
SET "s=!s:- =-;;! "
SET "s=!s: -=-! "
SET "s=!s:-;;-=-;-! "
SET "s=!s:-=%!"
SET "s=!s:_= %!"
SET "s=!s:;=';'%!"
SET "s=!s:;'';'=;;%!"
echo>>"%TMPFILE% !s!
)
COPY /Y "%TMPFILE%" "%USERPROFILE%\Desktop\Economic_Folder\economic_changes.txt"
IF EXIST "%TMPFILE%" (DEL "%TMPFILE%")
Here's a "dirty" trick:
#echo off
setlocal enabledelayedexpansion
set _FILE="%userprofile%\desktop\Economic_Folder\economic_changes.txt"
for /f %%a in ('type %_FILE% ^&^& echo.^>NUL 2^>%_FILE%') do (
SET s='%%a
SET s=!s:;= !
SET s=!s:- =-;;!
SET s=!s: -=-!
SET s=!s:-;;-=-;-!
SET s=!s:-=%!
SET s=!s:_= %!
SET s=!s:;=';'%!
SET s=!s:;'';'=;;%!
echo !s!
) >> %_FILE%
The "algorithm":
type the file contents to be consumed by the for loop
Empty it (thanks to [SO]: How to create empty text file from a batch file?)
Append everything in (your original code)

remove a particular filename from the output of for loop

I have various files date wise as:
cpms_2015_09_01.txt
lms_2015_07_10.txt
kmps_2015_10_07.txt
lmps_2015_10_07.txt
cpmgs_2015_10_07.txt
I wanted to remove from the "for loop" files of today's date name
How can I do this, I wrote a code for which I can store the file paths of all files in:
XCOUNT_1=D:\check\cpms_2015_09_01.txt ...etc
But, there shouldn't be no XCOUNT for today's file name like %_2015_10_07%
I am struck at this section of code pointed below
DO ( IF NOT "_%year%_%day%_%month%.txt"=="!FTRIM_%%J!"
My code is below
SETLOCAL ENABLEDELAYEDEXPANSION
setlocal
SET /A MAXJ=1
SET /A J=1
echo %DATE%
set year=%date:~-4,4%
set year=%year: =%
set month=%date:~7,2%
set month=%month: =%
set day=%date:~4,2%
set day=%day: =%
FOR /F "usebackq tokens=*" %%i IN (`DIR /S /B D:\check\*.txt`) DO ( IF NOT "_%year%_%day%_%month%.txt"=="!FTRIM_%%J!" (
SET XCOUNT_!J!=%%~i
SET FNAME_!J!=%%~ni
SET MAXJ=!J!
SET /A J+=1
SET FTRIM_!nxi!=%%~nxi:~-10,10%
PAUSE
)
)
C:\Users\pwatson\bin>type atest.bat
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET /A J=1
SET /A MAXJ=0
FOR /F "usebackq tokens=*" %%i IN (`DIR /S /B C:\Python27-32\*.exe`) DO (
SET XCOUNT_!J!=%%~i
SET MAXJ=!J!
SET /A J+=1
)
SET XCOUNT
This produces:
C:\Users\pwatson\bin>call atest.bat
XCOUNT_1=C:\Python27-32\python.exe
XCOUNT_10=C:\Python27-32\Lib\site-packages\pip\_vendor\distlib\t64.exe
XCOUNT_11=C:\Python27-32\Lib\site-packages\pip\_vendor\distlib\w32.exe
XCOUNT_12=C:\Python27-32\Lib\site-packages\pip\_vendor\distlib\w64.exe
XCOUNT_13=C:\Python27-32\Lib\site-packages\setuptools\cli-32.exe
XCOUNT_14=C:\Python27-32\Lib\site-packages\setuptools\cli-64.exe
XCOUNT_15=C:\Python27-32\Lib\site-packages\setuptools\cli-arm-32.exe
XCOUNT_16=C:\Python27-32\Lib\site-packages\setuptools\cli.exe
XCOUNT_17=C:\Python27-32\Lib\site-packages\setuptools\gui-32.exe
XCOUNT_18=C:\Python27-32\Lib\site-packages\setuptools\gui-64.exe
XCOUNT_19=C:\Python27-32\Lib\site-packages\setuptools\gui-arm-32.exe
XCOUNT_2=C:\Python27-32\pythonw.exe
XCOUNT_20=C:\Python27-32\Lib\site-packages\setuptools\gui.exe
XCOUNT_21=C:\Python27-32\Scripts\easy_install-2.7.exe
XCOUNT_22=C:\Python27-32\Scripts\easy_install.exe
XCOUNT_23=C:\Python27-32\Scripts\pip.exe
XCOUNT_24=C:\Python27-32\Scripts\pip2.7.exe
XCOUNT_25=C:\Python27-32\Scripts\pip2.exe
XCOUNT_3=C:\Python27-32\w9xpopen.exe
XCOUNT_4=C:\Python27-32\Lib\distutils\command\wininst-6.0.exe
XCOUNT_5=C:\Python27-32\Lib\distutils\command\wininst-7.1.exe
XCOUNT_6=C:\Python27-32\Lib\distutils\command\wininst-8.0.exe
XCOUNT_7=C:\Python27-32\Lib\distutils\command\wininst-9.0-amd64.exe
XCOUNT_8=C:\Python27-32\Lib\distutils\command\wininst-9.0.exe
XCOUNT_9=C:\Python27-32\Lib\site-packages\pip\_vendor\distlib\t32.exe
Getting these back into the parent environment is another issue. I hope that dbenham might respond.
First of all, you can't have all of that code on the same line like that unless you tell batch where one command stops and the next command begins. Secondly, the code you have will only work on the command prompt and not in a batch file, because you need two %s when using for loop variables inside of batch files. Third, set /a is only used for math; use a regular set command when storing a string value.
Finally (and most importantly), you need delayed expansion to properly iterate your counter variable inside of your for loop.
This batch script should work:
#echo off
setlocal enabledelayedexpansion
set J=1
for /R "D:\TEST" %%I in (*.txt) do (
set XCOUNT_!J!=%%I
set /a J+=1
)
If you want to exclude a specific file from the output, wrap the set code in an if statement.
#echo off
setlocal enabledelayedexpansion
set J=1
for /R "D:\TEST" %%I in (*.txt) do (
if not "%%~nxI"=="test.txt" (
set XCOUNT_!J!=%%I
set /a J+=1
)
)

Batch File to Extract values when variable names change in each file

OK, I have hundred of files that have a text header in them that includes one or more entries for a set of eight different variables (name, host, year, month, hour, minute, second). The first time the value is displayed it looks like:
#name 4 10
3 4 DHARLAN
Every time after this (and the variable sets can appear 1 to 100 times per file) it shows up only as:
3 4 DHARLAN
The problem comes in that what happens to be a 4 in this case can be any value between 1 & 99. So in the next file it might be:
3 15 DHARLAN
So really the of eavh variables entries are something like:
3 ## <value>
Where ## is determined earlier in the header by:
#name ## X
I don't understand enoyugh about how FOR /F TOKENS works to get anything that comes close.
What I need is to parse a directory and end up with a file something like:
<filenameA> <name1> <host1> <year1> <month1> <day1> <hour1> <minute1> <second1>
<filenameA> <name2> <host2> <year2> <month2> <day2> <hour2> <minute2> <second2>
<filenameB> <name1> <host1> <year1> <month1> <day1> <hour1> <minute1> <second1>
...
What I have so far:
FOR /f "tokens=*" %%i IN ('dir /a-d /s /b') DO call :findfile "%%i"
:findfile
REM Print Filename
FINDSTR /B /M "#UGC">>output.txt
REM set Name Variable, need 2nd word (7th & if exists (8th) character) from this line only
FINDSTR /B "#name">%%n
REM Find all lines with name variable
FINDSTR /B "3 %n%">>output.txt
Help is greatly appreciated, even suggestions to a program that can do this.
Thoughts
So...This is how I read your question. You have many files with many values and for each file you want output a single line of all the file's variables. Each variable is composed of two lines. 1. The variable declaration (name) and 2. The variable value (DHARLAN). These lines are associated by a number (1 to 99). Is this correct?
This should get you started...
#echo off
setlocal EnableExtensions EnableDelayedExpansion
<nul set /p "=">output.txt
for /f "delims=" %%F in ('dir /a:-d /b /s') do if exist "%%~fF" (
set "name="
set "namenum="
set "host="
set "hostnum="
set "year="
set "yearnum="
set "month="
set "day="
set "daynum="
set "monthnum="
set "hour="
set "hournum="
set "minute="
set "minutenum="
set "second="
set "secondnum="
set "count=0"
for /f "usebackq delims=" %%L in ("%%~fF") do (
for /f "tokens=1,2,3*" %%X in ("%%L") do (
if "%%Y"=="!namenum!" set "name=%%Z" & set /a "count+=1"
if "%%Y"=="!hostnum!" set "host=%%Z" & set /a "count+=2"
if "%%Y"=="!yearnum!" set "year=%%Z" & set /a "count+=4"
if "%%Y"=="!monthnum!" set "month=%%Z" & set /a "count+=8"
if "%%Y"=="!daynum!" set "day=%%Z" & set /a "count+=16"
if "%%Y"=="!hournum!" set "hour=%%Z" & set /a "count+=32"
if "%%Y"=="!minutenum!" set "minute=%%Z" & set /a "count+=64"
if "%%Y"=="!secondnum!" set "second=%%Z" & set /a "count+=128"
if /i "%%X"=="#name" set "namenum=%%Y"
if /i "%%X"=="#host" set "hostnum=%%Y"
if /i "%%X"=="#year" set "yearnum=%%Y"
if /i "%%X"=="#month" set "monthnum=%%Y"
if /i "%%X"=="#day" set "daynum=%%Y"
if /i "%%X"=="#hour" set "hournum=%%Y"
if /i "%%X"=="#minute" set "minutenum=%%Y"
if /i "%%X"=="#second" set "secondnum=%%Y"
if "!count!" equ "255" (
echo %%~nxF !name! !host! !year! !month! !day! !hour! !minute! !second!>>output.txt
set "name="
set "namenum="
set "host="
set "hostnum="
set "year="
set "yearnum="
set "month="
set "day="
set "daynum="
set "monthnum="
set "hour="
set "hournum="
set "minute="
set "minutenum="
set "second="
set "secondnum="
set "count=0"
)
)
)
)
goto :eof
:End
endlocal
Update
Here is an updated version of the script above with comments. It should also address your comment below with the setup section and the cd command.
#echo off
setlocal EnableExtensions EnableDelayedExpansion
:: Setup
set "ResultsFolder=results"
set "ExportFile=output.txt"
:: Set the Working Directory
cd data
:: Verify that the Results folder exists
if not exist "%ResultsFolder%\*" md "%ResultsFolder%"
set "OutputFile=%ResultsFolder%\%ExportFile%"
:: Empty the results file.
<nul set /p "=">%OutputFile%
:: Loop through the files /a:-d in the directory and its subdirectories /s.
for /f "delims=" %%F in ('dir /a:-d /b /s') do if exist "%%~fF" (
call :Reset
rem Loop through the file contents and parse each line.
for /f "usebackq delims=" %%L in ("%%~fF") do (
for /f "tokens=1,2,3*" %%X in ("%%L") do (
rem Keep track of the variables.
if "%%Y"=="!namenum!" set "name=%%Z" & set /a "count+=1"
if "%%Y"=="!hostnum!" set "host=%%Z" & set /a "count+=2"
if "%%Y"=="!yearnum!" set "year=%%Z" & set /a "count+=4"
if "%%Y"=="!monthnum!" set "month=%%Z" & set /a "count+=8"
if "%%Y"=="!daynum!" set "day=%%Z" & set /a "count+=16"
if "%%Y"=="!hournum!" set "hour=%%Z" & set /a "count+=32"
if "%%Y"=="!minutenum!" set "minute=%%Z" & set /a "count+=64"
if "%%Y"=="!secondnum!" set "second=%%Z" & set /a "count+=128"
if /i "%%X"=="#name" set "namenum=%%Y"
if /i "%%X"=="#host" set "hostnum=%%Y"
if /i "%%X"=="#year" set "yearnum=%%Y"
if /i "%%X"=="#month" set "monthnum=%%Y"
if /i "%%X"=="#day" set "daynum=%%Y"
if /i "%%X"=="#hour" set "hournum=%%Y"
if /i "%%X"=="#minute" set "minutenum=%%Y"
if /i "%%X"=="#second" set "secondnum=%%Y"
rem When a full set is reached print it out.
if "!count!" equ "255" (
echo %%~nxF !name! !host! !year! !month! !day! !hour! !minute! !second!>>%OutputFile%
call :Reset
)
if "!count!" gtr "255" (
echo %%~nxF: Incomplete Set Encountered. Stopping parsing of this file, continuing to the next.
rem You can also use other validations to identify incomplete sets.
)
)
)
)
goto :eof
:: Reset all of the variables for the next set.
:Reset
set "name="
set "namenum="
set "host="
set "hostnum="
set "year="
set "yearnum="
set "day="
set "daynum="
set "month="
set "monthnum="
set "hour="
set "hournum="
set "minute="
set "minutenum="
set "second="
set "secondnum="
set "count=0"
goto :eof
:End
endlocal
Summary
This is a summary of what the script is doing and how it works.
The Main for loop, will loop through all files located within the current working directory. dir /a:-d /b /s
Inside this loop, we first setup the variables needed to keep track of the file variables. :Reset
The next for loop will open the file and read each line of the file. %%L
The third for loop will then parse the line for the relevant variable information. Retrieve the first, second, and all remaining tokens from the line (1,2,*) into variables (%%X, %%Y, %%Z)
Now perform logic to keep track of the variables sets. If the variable number has been set and this line matches the variable number, then save the variable value. Else if the variable name matches, retrieve the variable number for comparison on the following lines.
Also increment the set count number and when a full set has been discovered, write it to the output file with the filename.
Reset the variables for use with the next set.
If the count does not equal 255, the file is incorrectly formatted or has an incomplete set of variables.
Notes
This script is just what seems to be the best solution for the questions presented and the information provided therein. I have had to make assumptions about the files being processed and therefore may requires some modifications. If you want to show us a full examples of the file to be parsed, it would help in determining what to do.

Batch files - How to do mass change of all specific variables using for loop

The following code takes in all command line parameters of a batch file. In my case I have about 30 command line parameters and they are all numbers of 1, 2, or 3. I take them in then want to reassign them to other characters. I want each var, if it is a 1, change it to /*, if it's a 2, change it to */, if it's a 3, change it to #.
The first part works great, it's the second part of reassigning that I can't get the syntax for.
SETLOCAL ENABLEDELAYEDEXPANSION
set count=1
FOR %%i IN (%*) DO (
set var!count!=%%i
set var!count!=!var!count!:1=/*! <--don't work
set var!count!=!var!count!:2=*/! <--don't work
set var!count!=!var!count!:3=#! <--don't work
set /a count=!count!+1
)
The problem is the way of accessing the array members.
In your case, the best way seems to use a temp variable.
SETLOCAL ENABLEDELAYEDEXPANSION
set count=1
FOR %%i IN (%*) DO (
set "temp=%%i"
set "temp=!temp:1=/*!"
set "temp=!temp:2=*/!"
set "temp=!temp:3=#!"
set "var!count!=!temp!"
set /a count+=1
)
I think jeb has the simplest solution, but there are other options.
1) You can transfer the current value of count into a FOR variable. This is how I tend to do it.
SETLOCAL ENABLEDELAYEDEXPANSION
set count=1
FOR %%i IN (%*) DO (
for %%N in (!count!) do (
set "var%%N=%%i"
set "var%%N=!var%%N:1=/*!"
set "var%%N=!var%%N:2=*/!"
set "var%%N=!var%%N:3=#!"
)
set /a count+=1
)
2) You can use CALL to delay expansion of the outer variable, but I don't like this option because the normal expansion is not as safe as delayed expansion.
SETLOCAL ENABLEDELAYEDEXPANSION
set count=1
FOR %%i IN (%*) DO (
set "var!count!=%%i"
call set "var!count!=%%var!count!:1=/*%%"
call set "var!count!=%%var!count!:2=*/%%"
call set "var!count!=%%var!count!:3=#%%"
set /a count+=1
)

Resources