Hi Can anyone help me out in this problem.
I need to create multiple file?? i give with any example. In some folder, say Folder Records.
"Record" folder contain 1 file by name "example2tought1023.au" . i need to generate same file contains, multiple time just by increasing the numbers.
i should get result like this example2tought1023.au example3tought1024.au example4tought1025.au example5tought1026.au
This is what I currently have:
SET count=9
SET filename_1=example
SET filename_2=thought
SET extension=.au
SET start_1=2
SET start_2=1023
SET source=%filename_1%%start_1%%filename_2%%start_2%%extension%
FOR /L %%i IN (1, 1, %count%) DO (
REM These two lines do not work!
SET /a n=%start_1%+%%i
SET /a number_2=%start_2% + %%i
SET destination=%filename_1%%number_1%%filename_2%%number_2%%extension%
ECHO %destination%
REM COPY %source% %destination%
)
PAUSE
but the lines in the FOR /L loop do not work
You have mis-identified which lines are not working :-)
The problem you are having relates to when variables are expanded. Normal expansion using percents occurs when the line is parsed, and your entire FOR statement, including the parenthesised DO clause, is parsed in one go. So the following line
SET destination=%filename_1%%number_1%%filename_2%%number_2%%extension%
is seeing the values of %number_1% and %number_2% that existed before the loop was executed. Obviously not what you want. The solution is simple - you need to use delayed expansion (the value at run time instead of parse time). You do that by 1st enabling delayed expansion using setlocal enableDelayedExpansion, and then use !number_1! instead of %number_1%.
You are not consistent with your variable names (n vs number_1).
I think you want to count from 0 to count-1 instead of from 1 to count.
You do not have to explictly expand the variable when using a variable in a SET /A expression. You can simply use the variable name without percents or exclamations. But this only works with the SET /A command.
You can also perform multiple computations and assignments with a single SET /A command by using a comma between each assignment.
#echo off
setlocal enableDelayedExpansion
REM counts from 0 to count, so 8 = 9 copies
set count=8
set filename_1=example
set filename_2=thought
set extension=.au
set start_1=2
set start_2=1023
set source=%filename_1%%start_1%%filename_2%%start_2%%extension%
for /L %%i in (0, 1, %count%) do (
set /a "number_1=start_1+%%i, number_2=start_2+%%i"
set destination=%filename_1%!number_1!%filename_2%!number_2!%extension%
echo !destination!
REM copy %source% !destination!
)
pause
Related
Good evening. I enjoy modding a game in my free time, it's one those games where individual mods are packed into zip files and loaded in by simply placing said zips into a certain folder. I have hundreds of these zips and was hoping to make a batch that would pick out a random mod for me each time I use it instead of having to pick through them all myself, while placing all the unused ones into a disabled folder that I made to keep everything not being used all in one place. Every mod was prefixed with a name referring to what category it'd belong to, for example 'weapon_shotgun_GiantAngryGun9000.zip' or 'character_huck_Clown.zip'
How this batch script would work is that first it'd take every file with the specified prefixes currently in the mod folder and put them all into the disabled folder. It would then go through every single file in the disabled folder that has all the specified prefixes, pick a random file from each category, and move them into the mod folder. Currently I've gotten my batch to do all that is explained, except rather than pick a random of each, it keeps picking the alphabetically last one from each prefix list. I believe it's because the Num var being used to designate the index for the entries in the File array is not being modified or read, and in-spite my best efforts I cannot get it to work the way I'm hoping.
Any advice or solutions is appreciated, thank you for reading.
setlocal EnableDelayedExpansion
SET modFolder="C:\Game\Mods\"
SET disabledFolder="C:\Game\Mods\Disabled\"
SET itemListIndex=0
::Prefix names
SET Prefix1=Weapon_Shotgun_
set itemList[%itemListIndex%]=%Prefix1%
set /A itemListIndex+=1
SET Prefix2=Character_ThisPerson_
set itemList[%itemListIndex%]=%Prefix2%
set /A itemListIndex+=1
SET Prefix3=Weapon_Rifle_
set itemList[%itemListIndex%]=%Prefix3%
set /A itemListIndex+=1
for /l %%G in (0 1 %itemListIndex%) do (
if not "!itemList[%%G]!" == "" (
set num=0
for %%f in (!itemList[%%G]!*.zip) do (
set /A num+=1
set file[%num%]=%%f
)
set /A pick = !random! * %num% / 32768 + 1
echo Moving "!file[%pick%]!" to the mod folder
move "%disabledFolder%!file[%pick%]!" %modFolder%
)
)
set file[%num%]=%%f is echoed as set file[]='[name of file]' instead of the expected set file['(index number)']='[name of file]'
the written echo says Moving !file[]! to the mod folder instead of the expected Moving (name of file) to the mod folder
The pick variable echos as blank, implying num or random are not valid
#ECHO OFF
setlocal EnableDelayedExpansion
SET modFolder="C:\Game\Mods\"
SET disabledFolder="C:\Game\Mods\Disabled\"
SET itemListIndex=0
::Prefix names
SET Prefix1=Weapon_Shotgun_
set itemList[%itemListIndex%]=%Prefix1%
set /A itemListIndex+=1
SET Prefix2=Character_ThisPerson_
set itemList[%itemListIndex%]=%Prefix2%
set /A itemListIndex+=1
SET Prefix3=Weapon_Rifle_
set itemList[%itemListIndex%]=%Prefix3%
set /A itemListIndex+=1
for /l %%G in (0 1 %itemListIndex%) do (
if not "!itemList[%%G]!" == "" (
set num=0
for %%f in (!itemList[%%G]!*.zip) do (
set /A num+=1
set file[!num!]=%%f
)
set /A pick = !random! * !num! / 32768 + 1
CALL SET "PICKFILE=%%file[!pick!]%%"
REM echo Moving "!file[%pick%]!" to the mod folder
REM ECHO move "%disabledFolder%!file[%pick%]!" %modFolder%
echo Moving "!pickfile!" to the mod folder
ECHO move "%disabledFolder%!pickfile!" %modFolder%
)
)
GOTO :EOF
Your issue is that %num% and %pick% are the values of num and ``pick` when the outer loop (%%G) was parsed, that is, nothing.
The classic method is to use !num! for the run-time value, but you are using indirection, so you'd be tempted to use !file[!pick!]! which is ambiguous and resolved to pick. The call uses a subshell to resolve the ambiguity.
Move command disarmed by being echoed.
Despite having already received and accepted an answer, I have decided to post this to show you how I would do it.
#Echo Off
SetLocal EnableDelayedExpansion
Set "modFolder=C:\Game\Mods"
Set "disabledFolder=C:\Game\Mods\Disabled"
Rem Undefine existing variables
For /F "Delims==" %%A In ('Set item 2^>NUL') Do Set "%%A="
Rem Define filename prefixes
Set "itemListIndex=0"
For %%A In (
Weapon_Shotgun
Character_ThisPerson
Weapon_Rifle
) Do (Set /A itemListIndex+=1
Set "itemList[!itemListIndex!]=%%A_")
Rem Randomize itemListIndex
Set /A itemListIndex=(%RANDOM% %% itemListIndex)+1
Rem Define files based upon itemList[%itemListIndex%]
Set "itemFileIndex=0"
For %%A In ("!itemList[%itemListIndex%]!*.zip") Do (Set /A itemFileIndex+=1
Set "itemFile[!itemFileIndex!]=%%A")
Rem Randomize itemFileIndex
Set /A itemFileIndex=(%RANDOM% %% itemFileIndex)+1
Rem Move itemFile[%itemFileIndex%] to modFolder.
Echo Moving "!itemFile[%itemFileIndex%]!" to the mod folder
Move /Y "%disabledFolder%\!itemFile[%itemFileIndex%]!" "%modFolder%"
Pause
This way, you can easily append to the parenthesized list of prefixes, (which both significantly reduces your code and makes it simpler to maintain). It also makes more sense to randomize itemListIndex first, to reduce the number of returned .zip files for selection/moving.
Although I'm really a newbie in this field, I want to accomplish a task in batch scripting: There is a determinate folder of company contracts in a determinate path, each of this folders (approx. 400) has a common folder (2016) where there might be a file indicating there has been an inspection in this year. What i want is to print every company folder that has not any file in the common 2016 folder and a count of the times this happens.
This is what i have (and does not work at all):
set c=0
for %i /d in (*) do
for %j in ($%i\2016\*) do
if (%j==NUL) then (#echo $%i c+=1 echo %c)`
If you just want to know if there is a file in the 2016 directory you can do this:
#echo off
SetLocal EnableDelayedExpansion
set count=0
for %%i /d in (*) do (
REM first unset variable
set files=
for %%j in (%%i\2016\*) do (
REM will set variable each time a file is encountered
set files=present
)
if not DEFINED files (
REM No files in directory 2016
echo %%i
set /a count+=1
echo !count!
)
)
EndLocal
exit /b 0
I don't see why you use $ before each %i. If you execute this code from the command line use one % for the loop variables i and j. But in a batch-script you'll have to use two of them (%%i, %%j).
Another thing, c+=1 won't work except if you use set /a.
I used delayed expansion because each block code ( between (...)) is parsed as one single command (as if it was all on one line with && between the commands inside the block) and you can't just assign a new value to a variable and read that new value in the same command. That's also the reason why I use !count! instead of %count% (which will give the value before the block). If you'd rather not use delayed expansion, remove the SetLocal EnableDelayedExpansion and replace echo !count! with call echo %%count%% (is another way to read a new value in the same command)
Also, be aware that each echo will end its output with a carriage retur and a newline. So each echo will result in a new line of output.
I have a question how to set multiple files as variables in batch file? I trying to do something with below script:
move c:\*.gpg q:\
for %%F in ("q:\*.gpg") do (set file=%%~nxF)
if exist q:\*.gpg echo done copying files: %file%
Above works fine only with one file. If there are more than two it only echos one of them. How can I echo in one line all the files that where copied?
There are multiple problems with your code
for %%F in ("q:\*.gpg") do (set file=%%~nxF)
if exist q:\*.gpg echo done copying files: %file%
First, you're assigning new values to the variable file each loop and then overwriting it every time without doing anything. Therefore after the loop file will only contain the value in the last loop. Move the echo part to inside the loop instead
Another problem is that variables are expanded at parse time by default. You need to enable delayed expansion and use ! instead of % to make it expand at runtime
Setlocal EnableDelayedExpansion
for %%F in ("q:\*.gpg") do (
set file=%%~nxF
echo done copying file: !file!
)
If you want to echo all files at once then set the file variable to contain the list of files
for %%F in ("q:\*.gpg") do (
set file=!file!, %%~nxF
)
echo done copying files: %file%
The file existence check is redundant. You can check the exit code after moving and exit if the files weren't moved.
The variables are not constant so remember to activate the expansion delayed variable, here the expansion of the variable file must be delayed.
Delayed Expansion will cause variables to be expanded at execution time rather than at parse time, this option is turned on with the SETLOCAL command. When delayed expansion is in effect variables can be referenced using !variable_name! (in addition to the normal %variable_name% )
Delayed variable expansion is often useful when working with FOR Loops, normally an entire FOR loop is evaluated as a single command even if it spans multiple lines of a batch script.
This is the default behaviour of a FOR loop:
Example :
#echo off
setlocal
:: count to 5 storing the results in a variable
set _tst=0
FOR /l %%G in (1,1,5) Do (echo [%_tst%] & set /a _tst+=1)
echo Total = %_tst%
C:\> demo_batch.cmd
[0]
[0]
[0]
[0]
[0]
Total = 5
Notice that when the FOR loop finishes we get the correct total, so the variable correctly increments, but during each iteration of the loop
the variable is stuck at it's initial value of 0
The same script with EnableDelayedExpansion, gives the same final result but also displays the intermediate values:
#echo off
setlocal EnableDelayedExpansion
:: count to 5 storing the results in a variable
set _tst=0
FOR /l %%G in (1,1,5) Do (echo [!_tst!] & set /a _tst+=1)
echo Total = %_tst%
C:\> demo_batch.cmd
[0]
[1]
[2]
[3]
[4]
Total = 5
Notice that within the for loop we use !variable! instead of %variable%.
And your batch script can be written like that :
#echo off
Set "Ext=*.gpg"
set /a Count=0
Setlocal EnableDelayedExpansion
for %%F in ("q:\%Ext%") do (
SET /a Count+=1
set "file=%%~nxF"
echo Done copying file [!Count!] : !file!
)
SET /a "COUNT_TOT=%Count%"
ECHO.
ECHO Total of [%EXT%] files(s) : %Count% file(s)
pause
i need to check if multiple files chronologically exist in a folder. I am having some issues and hope you can assist me.
There are some invoices that needed to be checked - with number starting from 13073713 to 13106972. The invoices contain a prefix "F" and the credit nots "G" for example "F13106972.pdf" and "G13106972.pdf" the suffix .pdf. What i am trying to do is loop through the folder and output all the missing ones chronologically into the log.txt. What am i doing wrong?
#echo off & setlocal
set "Ordner=%userprofile%\Desktop\test"
set "Log=%userprofile%\Desktop\Test\log.txt"
set /a from=13073713
set /a to=13106972
del "%Log%" 2 > nul
for /L %%i in(%from%,1,%to%)do (
if not exist "%Ordner%\F%i.pdf" echo F%%i
if not exist "%Ordner%\G%i.pdf" echo G%%i) >> "%Log%"
#echo off
setlocal enableextensions disabledelayedexpansion
set "Ordner=%userprofile%\Desktop\test"
set "Log=%userprofile%\Desktop\Test\log.txt"
set "from=13073713"
set "to=13106972"
(for /L %%i in (%from% 1 %to%) do (
if not exist "%Ordner%\F%%i.pdf" echo F%%i
if not exist "%Ordner%\G%%i.pdf" echo G%%i
)) > "%Log%"
Mainly typo errors. Changed/corrected from your code:
set /a in only needed to indicate to the parser that the value indicated to be stored in the variable contains some kind of arithmetic operation that needs to be evaluated. In batch files, at the end, all the values are strings. Not an error in your code (it works), but not needed.
The replaceable parameter in your for command is %%i. All the references to it must use the same double percent while inside a batch file. Some of your references were %i
The space after the in clause is needed
Log file deletion has been removed. All the for command is enclosed in a block (parenthesis) and redirected to the log file. If it exist, it will be overwritten.
So, I was writing a small batch-file game, and came across this problem in the FOR loop.
This is a small chunk of my code.
If the player picks-up the rock, check if it is on the table, then put it in your pack.
The problem is the SET command doesn't work.
I guess that lines executes as : set %table1%=empty not : set table1=empty.
I feel like there is a simple solution to this problem, I've trying for a few days in my spare time, but haven't gotten it.
Any help is appreciated!
set take=rock
set table1=box
set table2=rock
set table3=wrench
for %%x in (%table1% %table2% %table3%) do (
if %%x==%take% (
set %%x=empty
set pack=%%x
goto tableRoom
)
)
The main problem with your code is set %%x=empty for a logical reason: the for loop is iterating over the list of the values inside the table variables, not over the name of the variables so you can not change the value of the variable when you don't have a reference to the variable, you have the value inside it.
Enabling delayed expansion and iterating over the names of the variables can solve the problem
#echo off
setlocal enableextensions enabledelayedexpansion
set "take=rock"
set "table1=box"
set "table2=rock"
set "table3=wrench"
for %%x in (table1 table2 table3) do (
if "!%%x!"=="%take%" (
set "%%x=empty"
set "pack=%take%"
goto tableRoom
)
)
:tableRoom
set table
exit /b
%%x will hold the name of the variable, so when !%%x! is executed it will be something like !table1!, retrieving the value inside the variable (when delayed expansion is enabled).
If the names of the used variables (table...) does not collide with anything else, and you don't want to use delayed expansion, it is possible to take the output of set table command (the list the variables with its values) and process this list with a for /f command, splitting the command output, separating variable name and value
#echo off
setlocal enableextensions disabledelayedexpansion
set "take=rock"
set "table1=box"
set "table2=rock"
set "table3=wrench"
for /f "tokens=1,* delims==" %%a in ('set table') do (
if "%%b"=="%take%" (
set "%%a=empty"
set "pack=%take%"
goto tableRoom
)
)
:tableRoom
set table
exit /b
The output of set command contains var=value. Each of the lines is splitted using the = as a delimiter to get two tokens (tokens=1,*). %%a will hold the first token (the variable name) and %%b the rest of the line (the value in the variable)
You can use a counter to now which table you're testing in your FOR loop and
set directly the table!N! as empty :
set take=rock
set table1=box
set table2=rock
set table3=wrench
setlocal enabledelayedexpansion
set $c=1
for %%x in (%table1% %table2% %table3%) do (
if %%x==%take% (
set table!$c!=empty
set pack=%%x
goto tableRoom
)
set /a $c+=1
)
:tableroom
echo table2 is now : %table2%