What is %f in the for loop command? - windows

From this example right here.
https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/for#additional-references
for %f in (*.doc *.txt) do type %f
In the preceding example, each file that has the .doc or .txt extension in the current directory is substituted for the %f variable until the contents of every file are displayed. To use this command in a batch file, replace every occurrence of %f with %%f. Otherwise, the variable is ignored and an error message is displayed.
Are these different from variables in this example?
https://www.tutorialspoint.com/batch_script/batch_script_variables.htm
set message=Hello World
echo %message%
What are these called? How do I manipulate them?

in batch scripting slang it is called for loop token and the example above will work only in the command prompt. For a batch file you'll need double %.
These tokens changes their values on each iteration of the for loop. Example (this can be executed in the command prompt):
for %a in (1 2) do #echo %a
this will have two iterations - in the first the value if the %%a token it will be 1 and on the seconds 2.
You can use for loops to read files (with /f switch and no quotes) ,to iterate files (with no switch) or directories (with /d switch), iterate through strings (again without switch but using wild cards in strings is not possible) to read files (with /f and no quotes), or process a string (again with /f).
you can also split the value of each iteration with "delims" option and then you'll need more consecutive letters :
for /f "tokens=1,2 delims=-" %a in ("1-2-3") do #echo %a:%b
this will split the string in the quotes by - and will take the first and the second part accessible by the %a and %b tokens.
More on for loops:
https://ss64.com/nt/for.html
https://ss64.com/nt/for2.html
https://ss64.com/nt/for_r.html
https://ss64.com/nt/for_d.html
https://ss64.com/nt/for_f.html
https://ss64.com/nt/for_cmd.html

Related

How to get displayed a system variable read from external txt file with FOR /F expanded?

I am making a query on a txt file via Windows command prompt, but the output displayed is actual content of txt file, instead of system variable.
Any idea how can I amend that?
FOR /F "tokens=1,2 delims=," %%G IN (Backup_Folder.txt) DO (
echo %%H
)
Output is
%USERPROFILE%\Documents\Electronic Arts
instead of
C:\Users\UserName\Documents\Electronic Arts
Content of Backup_Folder.txt is:
EA,%USERPROFILE%\Documents\Electronic Arts
I suggest to use in the batch file:
for /F "tokens=1* delims=," %%G IN (Backup_Folder.txt) do call echo %%H
It is better to use tokens=1* instead of tokens=1,2 in case of the folder path stored in the text file contains per chance also a comma, for example:
EA,%USERPROFILE%\Documents,Settings\Electronic Arts
The asterisk after 1 means the rest of the line after the comma(s) after first comma delimited string without further splitting up the line on commas. So with tokens=1* the loop variable G gets assigned EA and loop variable H gets assigned %USERPROFILE%\Documents,Settings\Electronic Arts. The usage of tokens=1,2 results in H gets assigned just %USERPROFILE%\Documents, for that example.
The command CALL is necessary in this specific case to get on execution of the body of the loop after replacing %%H by %USERPROFILE%\Documents\Electronic Arts in first parsing step the command line parsed a second time by Windows command interpreter to expand additionally %USERPROFILE%.
When the folder path read from text file is assigned to an environment variable, I recommend to use as command set "FolderPath=%%~H" or call set "FolderPath=%%~H" for getting all environment variable references in folder path already expanded before assigning the folder path to the environment variable.
The tilde character between %% and H results on a folder path like "%USERPROFILE%\Documents & Settings\Electronic Arts" stored in the text file that the surrounding double quotes are removed making it possible to use the environment variable for example in a command line like:
if exist "%FolderPath%\Game\game.exe" echo Game exists.
A space as well as &()[]{}^=;!'+,`~ in a file/folder name without or with path require the usage of surrounding double quotes as output by Windows command interpreter on last help page on running in a command prompt window cmd /?. In argument strings not being a file/folder name/path the additionally possible characters |<> require also that the entire argument string is enclosed in straight double quotes to get those redirection operators interpreted as literal characters.
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 /?
echo /?
for /?
set /?

Execute all commands in current folder sequentially

Assuming I have a bunch of sqlcmd commands in .cmd files, order alphabetically e.g.:
01.setup.cmd
02.version1.cmd
03.version2.cmd
04.version3.cmd
how could one sequentially execute these in correct order with another .cmd file?
On windows:
for /F "tokens=*" %a in ('dir /b *.cmd') do call "%a"
This just loops over the result of dir /b *.cmd calling each in turn.
explanation from the docs:
FOR /F processing of a text file consists of reading the file, one
line of text at a time and then breaking the line up into individual
items of data called 'tokens'. The DO command is then executed with
the parameter(s) set to the token(s) found.
So my command says:
"tokens=*" don't give me individual tokens, give me the whole line as one hit
%a - name the line variable %a (note: it'll needs to be escaped as %%a if you're putting it in a batch file
('dir /b *.cmd') This is the input that it'll loop over. A bare directory listing for all .cmd files
then what I want it to do. Call the command %a.
If I didn't add the tokens bit it would work fine until you find a space in the file names.

List of attributes for For Loop in cmd

I am looking for a list of attributes and what they do in a for loop inside the command prompt.
Specifically I have a .bat file that copies a file from the root of the C:\ drive and pastes it inside all folders found in a pre-specified directory (i.e. C:\Users\John\Test Directory).
This is the command:
#echo off
for /D %%a in (C:\Users\John\Test Directory\*.*) do xcopy /y /d C:\test_file.txt "%%a\"
The .bat does exactly what I need it to do, but I do not understand what the "%%a" does in the command. I see similar commands that use %%g, %%f, etc, but nothing that defines why those were chosen or what they specifically do. Are those attributes arbitrary or do they have a defined function? I seemingly can't find any information on the attributes so any insight is appreciated!
Arbitrary. You can use any letter, upper or lower, and even symbols.
for %%# in... do command %%#
would work just as well. But when working with multiple tokens per iteration, it's better to use the alphabet. Here's an example why:
for /f "usebackq tokens=1* delims==" %%I in ("textfile.txt") do (
set "config[%%~I]=%%~J"
)
This is because %%I contains the text matched prior to the first equal sign, and %%J contains everything after the first equal sign. This answer shows that example in context.
The answer to your question is hinted in the for command's documentation. help for in the cmd console for full details. Specifically:
Some examples might help:
FOR /F "eol=; tokens=2,3* delims=, " %i in (myfile.txt) do #echo %i %j %k
would parse each line in myfile.txt, ignoring lines that begin with
a semicolon, passing the 2nd and 3rd token from each line to the for
body, with tokens delimited by commas and/or spaces. Notice the for
body statements reference %i to get the 2nd token, %j to get the
3rd token, and %k to get all remaining tokens after the 3rd.
This page explains further:
FOR Parameters
The first parameter has to be defined using a single character, for example the letter G.
FOR %%G IN ...
In each iteration of a FOR loop, the IN ( ....) clause is evaluated and %%G set to a different value
If this clause results in a single value then %%G is set equal to that value and the command is performed.
If the clause results in a multiple values then extra parameters are implicitly defined to hold each. These are automatically assigned in alphabetical order %%H %%I %%J ...(implicit parameter definition)
If the parameter refers to a file, then enhanced variable reference can be used to extract the filename/path/date/size.
You can of course pick any letter of the alphabet other than %%G.
%%G is a good choice because it does not conflict with any of the pathname format letters (a, d, f, n, p, s, t, x) and provides the longest run of non-conflicting letters for use as implicit parameters.
G > H > I > J > K > L > M
Format letters are case sensitive, so using a capital letter is also a good way to avoid conflicts %%A rather than %%a.
Just in the interest of thoroughness, it should be pointed out that:
when using for in a cmd console, use single percents.
when using for in a bat script, use double percents.
Use a tilde when retrieving the iterative variable to strip surrounding quotation marks from the value. (e.g. "Hello world!" becomes Hello world!). It's convenient to use this to force a desired format. "%%~G" would always be quoted, whether the captured value was quoted or not. You should always do this when capturing file names with a for loop.
Tilde notation also allows expanding paths, retrieving file size, and other conversions. See the last couple of pages of help for in a cmd console for more details.

How to remove the last part of a string after underscore using Windows command line

I have a file as "RAAAAAAV.KKK9.Z01_YYYYMMDDhhmmss". I want to remove the last part after the underscore"_" using a one liner dos command. Please help.
Output required:
RAAAAAAV.KKK9.Z01
The following works
#echo off
set var=RAAAAAAV.KKK9.Z01_YYYYMMDDhhmmss
set "var=%var:_="&rem %
set var
To rename a specific file:
ren "RAAAAAAV.KKK9.Z01_20151009231015" *.Z01
To rename all files with extension like Z01_timestamp:
ren *.Z01_?????????????? *.Z01
To rename all files where the beginning of the extension is unknown:
for %F in (*.???_??????????????) do #for /f "delims=_" %X in ("%~xF") do #ren "%F" "%~nF%X"
If used in a batch script, then percents must be doubled:
#echo off
for %%F in (*.???_??????????????) do for /f "delims=_" %%X in ("%%~xF") do ren "%%F" "%%~nF%%X"
EDIT - 2015-10-10
If you really want to have precise control over which files get renamed, then you can use my JREN.BAT regular expression renaming utility - a hybrid JScript/batch script that runs natively on any Windows machine from XP onward. The following simple one liner strips off the underscore and timestamp from any file that has an extension consisting of any combination of letters and digits, followed by an underscore, followed by a 14 digit timestamp.
jren "(\.[A-Z0-9]+)_\d{14}$" $1 /i
Maybe already late, but I will share my founding anyway for benefit to others.
You can use batch sub-procedure/function
:leftStr STRING SEPARATOR RESULT_VAR
::get left string before some specific SEPARATOR
set "STRING=%~1" get arg1
set "RIGHT=%STRING:*%~2=%" anything after arg2
set "%~3=!STRING:%~2%RIGHT%=!" strip that substr
exit /b
Then you can call it from other places, works even inside for loop with delayedExpansion enabled.
..
call :leftStr "left_right" "_" varname
echo !varname!
#rem varname = left
note: this is not a fancy function, no error checking or such. You'd better make sure your input string, separator, return_var is already valid or no conflict with any other.
EDIT: forgot to mention, this is for arbitrary length string and separator, for a simple, fixed length you can just use %var:~-N1,N2% (with negative N1)

cmd for loop mass renaming again oneliner

I'm over my head with this - spent too much time searching already - evidently I don't understand the basics of CMD variables etc. - and it always gives me such a headache
why wouldn't this work?
for %a in (*) do ( set tmpx=%a & echo %tmpx% )
the above code outputs the value of %tmpx% in some other scope - and it is always constant
yes, i run setlocal ENABLEDELAYEDEXPANSION
basically i need to do a simple rename of all files in folder from constantstring_somenameXX.tif to somenameXX.tif, where i.e. constantstring=0000000005
i had to use set because other posts rightly suggested that %a in a for loop has a special behaviour, and the substitutions wouldn't work for it as it is.
i would prefer not to use scripts and/or powershell - unless not using them is impossible
thank you
for %a in (*) do ( set tmpx=%a & echo %tmpx% )
The problem with the previous code is delayed expansion. Yes, you enabled it, but you have not used it, and depending on how you enabled it, it will not work
In cmd, when a line or block of lines (code inside parenthesis) is reached, it is first parsed and then executed. During the parse phase, variable read operations are removed from the command, replaced with the value in the variable before the command starts to execute. So, if you change the value of a variable inside a line/block you can not retrieve the changed value inside the same line/block as there are no variable reads (they were replaced)
setlocal enabledelayedexpansion allows to replace (where needed) the variable read syntax from %var% to !var!, indicating to the parser that the read operation will be delayed until the execution phase.
So, in your case, your code should have been something like
setlocal enabledelayedexpansion & for %a in (*) do ( set "tmpx=%a" & echo !tmpx! )
BUT this will not work (in default configured environments).
cmd has two execution modes: batch file and command line. In your case, you are using command line (no escaped percent sign in for loop) and in command line mode the setlocal enabledelayedexpansion will not work. It is intended for batch files (see setlocal /?)
How to make it work from the command line? By default cmd is started with delayed expansion disabled and you can not enable it if not inside a batch file. But you can start cmd with delayed expansion enabled and run your command in this started instance (see cmd /?)
cmd /v:on /c "for %a in (*) do ( set "tmpx=%a" & echo !tmpx! )"
Anyway, to solve your rename problem, delayed expansion is not needed
for %a in (*_*.tif) do for /f "tokens=1,* delims=_" %b in ("%~nxa") do echo ren "%a" "%c"
That is, for each tif file with an underscore, take the name and extension of the file (%~nxa) as a string, and using the underscore as a delimiter between tokens, retrieve the first token (the text on the left of the first underscore) in %b and the rest of the text (to the right of the underscore) into %c. Now, just rename the original file name (stored in %a) to the contents of %c (the text on the right of the underscore)
In this code rename operations are only echoed to console. If the output is correct, remove the echo command.
! is the character to use rather than % when wanting execution time value. % does when it's read value.
CMD was written by IBM engineers and they were trying to make MSDos a programming language while making sure Dos commands ran the same. So we get a hodge podge.
& seperates commands on a line.
&& executes this command only if previous command's errorlevel is 0.
|| (not used above) executes this command only if previous command's errorlevel is NOT 0
> output to a file
>> append output to a file
< input from a file
| output of one command into the input of another command
^ escapes any of the above, including itself, if needed to be passed to a program
" parameters with spaces must be enclosed in quotes
+ used with copy to concatinate files. E.G. copy file1+file2 newfile
, used with copy to indicate missing parameters. This updates the files modified date. E.G. copy /b file1,,
%variablename% a inbuilt or user set environmental variable
!variablename! a user set environmental variable expanded at execution time, turned with SelLocal EnableDelayedExpansion command
%<number> (%1) the nth command line parameter passed to a batch file. %0 is the batchfile's name.
%* (%*) the entire command line.
%<a letter> or %%<a letter> (%A or %%A) the variable in a for loop. Single % sign at command prompt and double % sign in a batch file.

Resources