Batch increment part of variable name - variables

How can I increment part of a variable name?
EG. i want to increment
filename holds something like mmddyyyy-prev01-Database.mdb
and I'm trying to rename it to mmddyyyy-prev02-Database.mdb
With the code
Setlocal EnableDelayedExpansion
set /a nextFileName=!fileName:~0,13!!fileName:~13!+1
and I get the error
Missing operator.
I am using this to make a batch sub that will recursively rename the prevXX items so that the newest one is always prev01. I'm also doing regular setlocal in my method to keep the variables from getting mixed up between the deeper calls

I'm going the hard way:
#ECHO OFF &SETLOCAL disableDelayedExpansion
FOR /f "delims=" %%x IN ('DIR /b /a-d /o-n *-prev*-Database.mdb') DO (
FOR /f "tokens=1-3*delims=v-" %%a IN ("%%~x") DO (
FOR /f "tokens=*delims=0" %%e IN ("0%%c") DO (
FOR /f %%f IN ('SET /a %%e+1') DO (
IF %%f LEQ 9 (
ECHO REN "%%~x" "%%~a-%%~bv0%%~f-%%~d"
) ELSE (
ECHO REN "%%~x" "%%~a-%%~bv%%~f-%%~d"
)
)
)
)
)
Just remove the ECHOs to make it working.

SET /A won't allow you do this.
You'll have to break up into two lines, like this:
SET BaseFileName=!FileName:~0,13!
SET /A Counter=!FileName:~13!+1
Then, put the pieces back together:
SET NextFileName=%BaseFileName%%Counter%-Database.mdb
NOTE: This will not handle your leading 0...you'll have to write more code for that.

...
set filename=mmddyyyy-prev01-Database.mdb
call :nextname
ren %filename% %newname%
...
:nextname
set /a newname=1%filename:~13,2%+1
set newname=%filename:~0,13%%newname:~-2%%filename:~15%
goto :eof
Whether you'd use ren %filename% %newname% or ren !filename! !newname! is a matter of context. You've posted insufficient code to be certain. If, as I suspect, you are executing the ren in a loop, then you would need the !var! form and delayedexpansion (with which you appear familiar.) Within the subroutine :nextname, the %var% form should be used.
but remember that you need to rename your existing files in reverse-alphabetical order, so
mmddyyyy-prev03-Database.mdb becomes mmddyyyy-prev04-Database.mdb
mmddyyyy-prev02-Database.mdb becomes mmddyyyy-prev03-Database.mdb
mmddyyyy-prev01-Database.mdb becomes mmddyyyy-prev02-Database.mdb

Related

batch script for file system: use of for-loop variable in another nested for-loop

the last 4-5 hours I spent trying to get my script fixed, and tried several things, but it still doesn't work as supposed. Here is the working part:
#echo off
rem automatically sort MP3s into an existing structure or add folders if needed
rem example of MP3-file pattern: Wu-Tang Clan - Gravel Pit (LP Version Clean).mp3
SETLOCAL
rem set variables
SET "source=g:\music\folder"
SET "str=Wu-Tang Clan - Gravel Pit (LP Version Clean).mp3"
SET "test=%source%\%str%"
rem split the filename from the remaining path. Take the left part
rem and assign it to %band% while the right part gets assigned to %song%
FOR /f "delims=" %%i IN ("%test%") DO SET "result=%%~nxi"
SET "band=%result: - =" & SET "song=%"
rem If there is no such folder (%band%), create it
IF not exist "%source%\%band%" MD "%source%\%band%"
rem As soon as there definetely is a fitting folder
rem move the file over there.
MOVE /-Y "%source%\%result%" "%source%\%band%"
The next step would be to enhance the code by a for-loop so I don't have to edit the script for every single one of my 3k+ files ;)
I tried really hard to get this code going, but failed:
#echo off
SETLOCAL
SET "source=g:\music\folder"
FOR %%f IN (%source%\*.mp3) DO (
echo %%f
FOR /f "delims=" %%i IN ("%%f") DO SET "result=%%~nxi"
SET "band=!result: - =" & SET "song=%"
IF not exist "%source%\%band%" MD "%source%\%band%"
MOVE /-Y "%source%\%result%" "%source%\%band%"
)
pause
So I added a for-loop and %%f was correctly filled at first and wasn't in the next for-loop.
FOR %%f IN (%source%\*.mp3) DO (
echo %%f
That resulted in: "g:\music\folder\Wu-Tang Clan - Gravel Pit (LP Version Clean).mp3"
Like it was supposed to. But after that
FOR /f "delims=" %%i IN ("%%f") DO SET "result=%%~nxi"
result and every following variable was empty, always.
I tried to fix it with a second variable as a 'helper':
FOR %%f IN (%source%\*.mp3) DO (
SET "helper=%%f"
FOR /f "delims=" %%i IN ("%helper%") DO SET "result=%%~nxi"
Even added 'enabledelayedexpansion' after I read about that and went for
FOR /f "delims=" %%i IN ("!helper!") DO SET "result=%%~nxi"
still doesn't work.
Now I could really need some help and would really appreciate it :)
regards Phoenix
Next code snippet could work. Note that the SET "band=%result: - =" & SET "song=%" trick can't be performed using ! delayed expansion unlike %-expansion. Therefore, that command is moved to the :myset subroutine and executed via call command.
#echo off
SETLOCAL EnableExtensions EnableDelayedExpansion
SET "source=g:\music\folder"
FOR %%f IN (%source%\*.mp3) DO (
echo %%f
FOR /f "delims=" %%i IN ("%%f") DO SET "result=%%~nxi"
call :myset
IF not exist "%source%\!band!" MD "%source%\!band!"
MOVE /-Y "%source%\!result!" "%source%\!band!"
)
goto :skipMyset
:myset
SET "band=%result: - =" & SET "song=%"
goto :eof
:skipMyset
pause
Resources (required reading):
(command reference) An A-Z Index of the Windows CMD command line
(additional particularities) Windows CMD Shell Command Line Syntax
(special page) EnableDelayedExpansion

In Windows batch - how do I replace single quote with escape single quote to feed SQL

With my Windows batch file, I have following SQL statement:
FOR /F "eol=; tokens=1,2,3,4,5,6* delims=, " %a in (myfile.txt) do(
sqlcmd -SmYSerbver -Uhhh -P12345 -dmyDB_Admin -Q"insert into tableA (UserID,FirstName,LastName,Email,DisplayName,OrgUnit,LoadDate) values('%%a','%%b','%%c','%%d','%%e','%%f',getdate())"
)
One user's last name is "O'Brien" - my variable %%c is evaluated as O'Brien.
How do I operate to make %%c evaluated as "O''Brien"?
You need an interim variable to do string replacements as the related syntax cannot be applied to for variables like %%c directly. For this to work, delayed variable expansion needs to be enabled, and the interim variable needs to be expanded using !! rather than %%.
The following illustrates how to accomplish that for the value in %%c, using the interim variable c_tmp:
setlocal EnableDelayedExpansion
for /F "eol=; tokens=1,2,3,4,5,6* delims=, " %%a in (myfile.txt) do (
set "c_tmp=%%c" & set "c_tmp=!c_tmp:'=''!"
sqlcmd -SmYSerbver -Uhhh -P12345 -dmyDB_Admin -Q"insert into tableA (UserID,FirstName,LastName,Email,DisplayName,OrgUnit,LoadDate) values('%%a','%%b','!c_tmp!','%%d','%%e','%%f',getdate())"
)
endlocal
When %%c contains a string O'Brien, c_tmp will finally contain O''Brien.
Of course you can do also other replacements by modifying the command set "c_tmp=!c_tmp:'=''!" accordingly.
Perhaps you could escape single quote with \ like O\'brian if it's sqlcmd failing to insert.
If the file containing single quotes that does not use for delimitation of values, then you could replace all occurrences in an intermediate file.
(
echo O'Brian1a, O'Brian1b, O'Brian1c, O'Brian1d, O'Brian1e, O'Brian1f
echo O'Brian2a, O'Brian2b, O'Brian2c, O'Brian2d, O'Brian2e, O'Brian2f
echo O'Brian3a, O'Brian3b, O'Brian3c, O'Brian3d, O'Brian3e, O'Brian3f
)>%tmp%\myfile.tmp
(
for /f "delims=" %%i in (%tmp%\myfile.tmp) do (
set "i=%%i"
setlocal enabledelayedexpansion
echo !i:'=\'!
)
)>%tmp%\int-myfile.tmp
for /f "tokens=1-6 delims=, " %%a in (%tmp%\int-myfile.tmp) do (
echo '%%a','%%b','%%c','%%d','%%e','%%f'
)
output:
'O\'Brian1a','O\'Brian1b','O\'Brian1c','O\'Brian1d','O\'Brian1e','O\'Brian1f'
'O\'Brian2a','O\'Brian2b','O\'Brian2c','O\'Brian2d','O\'Brian2e','O\'Brian2f'
'O\'Brian3a','O\'Brian3b','O\'Brian3c','O\'Brian3d','O\'Brian3e','O\'Brian3f'
As a last resort you can always choose with which character you replace in the line: echo !i:'=\'!

Batch: variable definition useable in count loop

In my batch I want to copy a variable amount of source- to target destinations.
I want to define like this:
#setlocal EnableDelayedExpansion
set source1="C:\folder1"
set target1="f:\folder1"
set source2="C:\folder2"
set target2="f:\folder2"
...
set sourcen="C:\foldern"
set targetn="f:\foldern"
Dependently from a defined amount of folders
set numFolder=5
I want to go through the folders in a loop:
set /a COUNT=0
:LOOP
echo %COUNT%
set /a COUNT+=1
rem write the NAME of the parameter variable (source1,source2 etc.) in nameor
set "nameor=source%COUNT%"
rem write the VALUE of the parameter variable (source1,source2 etc.) into origin ("C:\folder1", "C:\folder2")
set "origin=%nameor%"
echo %origin%
if %COUNT% lss %numFolder% goto LOOP
When I show
echo %nameor%
I get what I expectet: source1, source2 etc.
but
echo %%%origin%%%
only provides
source1
instead of the expected value
"C:\folder1"
I thought, that I could resolve this by using DelayedExpansion but what did I miss?
To avoid confusion for me, I change the "origin" to "source". E.g. set "origin=%nameor%" changed to set "source=%nameor%".
To print out "C:\folder1" to "C:\foldern", you should use echo !%source%!, else you will just see "source1" to "sourcen".
Your problem is just about array element management. Try this:
#echo off
setlocal EnableDelayedExpansion
rem Define the two arrays
set i=0
for %%a in ("C:\folder1=f:\folder1"
"C:\folder2=f:\folder2"
"C:\foldern=f:\foldern") do (
set /A i+=1
for /F "tokens=1,2 delims==" %%b in (%%a) do (
set source!i!="%%a"
set target!i!="%%b"
)
)
rem Show up to numFolder elements of both arrays
set numFolder=5
for /L %%i in (1,1,%numFolder%) do (
echo %%i- Source%%i=!source%%i!, Target%%i=!target%%i!
)
The first part is equivalent to your series of individual element assignments. In this way is easier to add new pairs of values.
For further description on array management in Batch files, see: Arrays, linked lists and other data structures in cmd.exe (batch) script

How to split an ip address into seperate octets and perform arithmetic in cmd

What I am trying to do is configure some vlan scopes via cmd. What I have accomplished so far is to retrieve the IP Address of the Domain Controller and remove the space in front of the value. I have accomplished this using the following commands:
rem extract ip address via local cmd
for /f "tokens=2 delims=:" %i in ('ipconfig ^| find /i "IPv4 Address"') do set ip_address=%i
example result: set ip_address= 10.0.0.25
rem remove empty space from ip address var
set ip_address=%ip_address: =%
echo %ip_address% now results in 10.0.0.25 without the space in front.
What I would like to do next is split the ip_address variable in separate octet variables so that arithmetic can be performed on the octet of choice.
For example: 10.0.0.25 could then be manipulated to reflect 10.[+100].0.[-24]
the desired result would then be 10.100.0.1
I would prefer to accomplish this strictly using windows command line but if a better method exits I am open to suggestions.
Thanks in advance
Joel
Try this to split up the octets into variables.
#echo off
set "ip=10.0.0.25"
SET "offsets=0.100.0.-24"
#echo off
for /f "tokens=1-4 delims=. " %%a in ("%ip%") do (
set octetA=%%a
set octetB=%%b
set octetC=%%c
set octetD=%%d
)
FOR /f "tokens=1-4 delims=." %%a in ("%offsets%") do (
SET /a octetA+=%%a
SET /a octetB+=%%b
SET /a octetC+=%%c
SET /a octetD+=%%d
)
echo "%octetA%","%octetB%","%octetC%","%octetD%"
pause
This is the same solution of foxidrive, but squashed a little... :)
#echo off
set "ip= 10.0.0.25"
SET "offsets=0.100.0.-24"
for /F "tokens=1-4 delims=. " %%a in ("%ip%") do (
for /F "tokens=1-4 delims=." %%i in ("%offsets%") do (
set /A octetA=%%a+%%i, octetB=%%b+%%j, octetC=%%c+%%k, octetD=%%d+%%l
)
)
echo "%octetA%","%octetB%","%octetC%","%octetD%"
pause
Are you aware of autohotkey?
Also, you could try a powershell script.

Variables in loops Dont Work, Batch

This is the new Script and it Still Doesn't Work
I Get The syntax of the command is incorrect.
on FOR /F "USEBACKQ tokens=*" %%A IN (TYPE "C:\Windows\System32\tasks\at!num! ^| FIND "Command") DO (
SETLOCAL ENABLEDELAYEDEXPANSION
set num=1
:START
IF NOT EXIST "C:\Windows\System32\tasks\at%num%" (GOTO:EOF)
FOR /F "USEBACKQ tokens=*" %%A IN (`TYPE "C:\Windows\System32\tasks\at!num! ^| FIND "Command"`) DO (
set var=%%A
ECHO %var%
SET /a num=%num%+1
PAUSE
)
GOTO:START
To understand your code, I'm going to break it down into logic first then try to solve it. Let me know if I miss a detail...
Set num var to 0
Begin :Loop
set num var to its current value ::NOT NEEDED - You've specified this prior to the GOTO
increment num var by +1
if myfolder\at* file exists then read at%num% and find a string then output that line to %tmp%\1.txt ::Need quotations on file location.
set F var to the line stored in %tmp%\1.txt
set F="%%F: =%%" ::Please explain what you are trying to do with this command.
set F to start on 10th character and remove the last 11 characters from the line.
echo the variable
If it doesn't exist, exit, but if it does return to :Loop
You should tell us what you are attempting. If it is as simple as saving a variable from a text file output, set F=<file.txt will work. If it didn't, then something happened prior to that command. Still... what is set F="%%F: =%%"?
Unless you are using a FOR loop variable, there is no need to use %% on each end of the variable.
If this were a FOR loop, it would look like this:
SETLOCAL ENABLEDELAYEDEXPANSION
set num=1
:START
IF NOT EXIST "myFolder\at%num%.txt" (GOTO:EOF)
FOR /F "USEBACKQ tokens=*" %%A IN (`TYPE "myFolder\at%num%.txt" ^| FIND /i "string"`) DO (
PAUSE
SET var=%%A
ECHO !var!
PAUSE
SET var=!var: =!
ECHO !var!
PAUSE
SET var=!var:~10,-11!
ECHO !var!
PAUSE
SET /a num=!num!+1
ECHO !num!
PAUSE
)
GOTO:START
One good practice to check if commands are working, such as SET, insert an ECHO on the variable and a PAUSE right after each time you believe the variable should be changed. This will track what has changed on the variable so you can see if your command was correct and the changes were made.
I'd suggest using Batch's inbuilt function for loops, see here.
Conditionally perform a command for a range of numbers
Syntax
FOR /L %%parameter IN (start,step,end) DO command
Or maybe iterating over files in a folder would be better for what you are trying to do?
Loop through files (Recurse subfolders)
Syntax
FOR /R [[drive:]path] %%parameter IN (set) DO command
Or iterating over file contents?
Loop command: against a set of files - conditionally perform
a command against each item.
Syntax
FOR /F ["options"] %%parameter IN (filenameset) DO command
FOR /F ["options"] %%parameter IN ("Text string to process") DO command
This site has plenty of examples here which should point you in the right direction.
There are a few issues with your code, I've amended as follows to get the variable populated with the contents of the temp file.
set num=0
:Loop
set /a num=%num%+1
if exist "myFolder\at*" (
TYPE "myFolder\at%num%" | FINDSTR "\<Command\>" > "%temp%\1.txt"
set /P F=<"%TEMP%\1.txt"
Echo %F%
Pause
)
I don't know if this is the problem, but have you tried enabling:
setlocal enabledelayedexpansion
Then, inside the loop (or the IF(...)), you use !foo! to signify environment variables instead of %foo%.
See setlocal /? and set /? for more information.