I am trying to run this line:
for /f "tokens=1* delims=" %%a in ('date /T') do set datestr=%%a
From command line, but got the error:
%%a was unexpected at this time.
Then I searched and found:
"was unexpected at this time."
%%A was unexpected at this time
The problem is to escape % on batch file I need to add two of them, but on the command line I only need one of it. How can I write it compatible with both command line and batch file keeping it in one and same line of code?
Not a one liner, but when you can live with two lines
set "pp=%%"
for /f "tokens=1* delims=" %pp:~-1%a in ('date /T') do set datestr=%pp:~-1%a
Why not use
set "datestr=%date%"
which will set datestr to the current value of date as a built-in magic variable?
Of course, this doesn't cover the manipulation that is likely to be required since %date% and date /t both return the date in the format that the user has chosen - there's no universal format available directly in batch; you'd need to use wmic which may or may not be available to the user.
if you are executing this from command line you need single %:
for /f "tokens=1* delims=" %a in ('date /T') do set datestr=%a
Double percentage is for running this from .bat or .cmd file.
I would like to know how to loop through lines with colons in a text file using a Windows batch file and get the second token and write that token to disk.
eg:-
Name : -I$HAN-
I want -I$HAN- to write to disk.
#echo off
set "file=name_of_input_file"
set "outfile=name_of_output_file"
for /f "tokens=2 delims=:" %%a in (%file%) do echo %%a>>%outfile%
As you also have a space either side of the colon and probably don't want it adding to your output, therefore try:
#Echo Off
Set "file=name_of_input_file"
Set "outfile=name_of_output_file"
(For /F "UseBackQ Tokens=1* Delims=: " %%A in ("%file%") Do Echo=%%B)>"%outfile%"
I have a java properties file to parse, it contains key value pairs of the form key=value, one on each line.
After digging around on the site, I've found this site that explains the FOR syntax, and also this question.
I constructed the following line to get the value of the backupdir.windows property in config.properties:
for /f "delims== tokens=2" %i in ('findstr backupdir.windows= config.properties') do #echo %i
The above works if you type it at the command prompt, but if I save it as a file 'test.cmd' and then execute that, I get 'i was unexpected at this time.'
Same thing happens if I change the extension to .bat (in case doing so would make it use
earlier MSDOS syntax).
What's going wrong here? I'm running Windows 7.
Better to do it like this:
#echo off
for /f "tokens=2 delims==" %%a in ('findstr /b /i "backupdir.windows" config.properties') do echo %%a
it needs to be %%i in a batch file. And just %i on the command line.
I would like to know how to loop through each line in a text file using a Windows batch file and process each line of text in succession.
I needed to process the entire line as a whole. Here is what I found to work.
for /F "tokens=*" %%A in (myfile.txt) do [process] %%A
The tokens keyword with an asterisk (*) will pull all text for the entire line. If you don't put in the asterisk it will only pull the first word on the line. I assume it has to do with spaces.
For Command on TechNet
If there are spaces in your file path, you need to use usebackq. For example.
for /F "usebackq tokens=*" %%A in ("my file.txt") do [process] %%A
From the Windows command line reference:
To parse a file, ignoring commented lines, type:
for /F "eol=; tokens=2,3* delims=," %i in (myfile.txt) do #echo %i %j %k
This command parses each line in Myfile.txt, ignoring lines that begin with a semicolon and passing the second and third token from each line to the FOR body (tokens are delimited by commas or spaces). The body of the FOR statement references %i to get the second token, %j to get the third token, and %k to get all of the remaining tokens.
If the file names that you supply contain spaces, use quotation marks around the text (for example, "File Name"). To use quotation marks, you must use usebackq. Otherwise, the quotation marks are interpreted as defining a literal string to parse.
By the way, you can find the command-line help file on most Windows systems at:
"C:\WINDOWS\Help\ntcmds.chm"
In a Batch File you MUST use %% instead of % : (Type help for)
for /F "tokens=1,2,3" %%i in (myfile.txt) do call :process %%i %%j %%k
goto thenextstep
:process
set VAR1=%1
set VAR2=%2
set VAR3=%3
COMMANDS TO PROCESS INFORMATION
goto :EOF
What this does:
The "do call :process %%i %%j %%k" at the end of the for command passes the information acquired in the for command from myfile.txt to the "process" 'subroutine'.
When you're using the for command in a batch program, you need to use double % signs for the variables.
The following lines pass those variables from the for command to the process 'sub routine' and allow you to process this information.
set VAR1=%1
set VAR2=%2
set VAR3=%3
I have some pretty advanced uses of this exact setup that I would be willing to share if further examples are needed. Add in your EOL or Delims as needed of course.
Improving the first "FOR /F.." answer:
What I had to do was to call execute every script listed in MyList.txt, so it worked for me:
for /F "tokens=*" %A in (MyList.txt) do CALL %A ARG1
--OR, if you wish to do it over the multiple line:
for /F "tokens=*" %A in (MuList.txt) do (
ECHO Processing %A....
CALL %A ARG1
)
Edit: The example given above is for executing FOR loop from command-prompt; from a batch-script, an extra % needs to be added, as shown below:
---START of MyScript.bat---
#echo off
for /F "tokens=*" %%A in ( MyList.TXT) do (
ECHO Processing %%A....
CALL %%A ARG1
)
#echo on
;---END of MyScript.bat---
#MrKraus's answer is instructive. Further, let me add that if you want to load a file located in the same directory as the batch file, prefix the file name with %~dp0. Here is an example:
cd /d %~dp0
for /F "tokens=*" %%A in (myfile.txt) do [process] %%A
NB:: If your file name or directory (e.g. myfile.txt in the above example) has a space (e.g. 'my file.txt' or 'c:\Program Files'), use:
for /F "tokens=*" %%A in ('type "my file.txt"') do [process] %%A
, with the type keyword calling the type program, which displays the contents of a text file. If you don't want to suffer the overhead of calling the type command you should change the directory to the text file's directory. Note that type is still required for file names with spaces.
I hope this helps someone!
The accepted answer is good, but has two limitations.
It drops empty lines and lines beginning with ;
To read lines of any content, you need the delayed expansion toggling technic.
#echo off
SETLOCAL DisableDelayedExpansion
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ text.txt"`) do (
set "var=%%a"
SETLOCAL EnableDelayedExpansion
set "var=!var:*:=!"
echo(!var!
ENDLOCAL
)
Findstr is used to prefix each line with the line number and a colon, so empty lines aren't empty anymore.
DelayedExpansion needs to be disabled, when accessing the %%a parameter, else exclamation marks ! and carets ^ will be lost, as they have special meanings in that mode.
But to remove the line number from the line, the delayed expansion needs to be enabled.
set "var=!var:*:=!" removes all up to the first colon (using delims=: would remove also all colons at the beginning of a line, not only the one from findstr).
The endlocal disables the delayed expansion again for the next line.
The only limitation is now the line length limit of ~8191, but there seems no way to overcome this.
Or, you may exclude the options in quotes:
FOR /F %%i IN (myfile.txt) DO ECHO %%i
Here's a bat file I wrote to execute all SQL scripts in a folder:
REM ******************************************************************
REM Runs all *.sql scripts sorted by filename in the current folder.
REM To use integrated auth change -U <user> -P <password> to -E
REM ******************************************************************
dir /B /O:n *.sql > RunSqlScripts.tmp
for /F %%A in (RunSqlScripts.tmp) do osql -S (local) -d DEFAULT_DATABASE_NAME -U USERNAME_GOES_HERE -P PASSWORD_GOES_HERE -i %%A
del RunSqlScripts.tmp
If you have an NT-family Windows (one with cmd.exe as the shell), try the FOR /F command.
The accepted anwser using cmd.exe and
for /F "tokens=*" %F in (file.txt) do whatever "%F" ...
works only for "normal" files. It fails miserably with huge files.
For big files, you may need to use Powershell and something like this:
[IO.File]::ReadLines("file.txt") | ForEach-Object { whatever "$_" }
or if you have enough memory:
foreach($line in [System.IO.File]::ReadLines("file.txt")) { whatever "$line" }
This worked for me with a 250 MB file containing over 2 million lines, where the for /F ... command got stuck after a few thousand lines.
For the differences between foreach and ForEach-Object, see Getting to Know ForEach and ForEach-Object.
(credits: Read file line by line in PowerShell )
Modded examples here to list our Rails apps on Heroku - thanks!
cmd /C "heroku list > heroku_apps.txt"
find /v "=" heroku_apps.txt | find /v ".TXT" | findstr /r /v /c:"^$" > heroku_apps_list.txt
for /F "tokens=1" %%i in (heroku_apps_list.txt) do heroku run bundle show rails --app %%i
Full code here.
To print all lines in text file from command line (with delayedExpansion):
set input="path/to/file.txt"
for /f "tokens=* delims=[" %i in ('type "%input%" ^| find /v /n ""') do (
set a=%i
set a=!a:*]=]!
echo:!a:~1!)
Works with leading whitespace, blank lines, whitespace lines.
Tested on Win 10 CMD
I need to be able to load the entire contents of a text file and load it into a variable for further processing.
How can I do that?
Here's what I did thanks to Roman Odaisky's answer.
SetLocal EnableDelayedExpansion
set content=
for /F "delims=" %%i in (test.txt) do set content=!content! %%i
echo %content%
EndLocal
If your set command supports the /p switch, then you can pipe input that way.
set /p VAR1=<test.txt
set /? |find "/P"
The /P switch allows you to set the value of a variable to a line of
input entered by the user. Displays the specified promptString before
reading the line of input. The promptString can be empty.
This has the added benefit of working for un-registered file types (which the accepted answer does not).
Use for, something along the lines of:
set content=
for /f "delims=" %%i in ('filename') do set content=%content% %%i
Maybe you’ll have to do setlocal enabledelayedexpansion and/or use !content! rather than %content%. I can’t test, as I don’t have any MS Windows nearby (and I wish you the same :-).
The best batch-file-black-magic-reference I know of is at http://www.rsdn.ru/article/winshell/batanyca.xml. If you don’t know Russian, you still could make some use of the code snippets provided.
You can use:
set content=
for /f "delims=" %%i in ('type text.txt') do set content=!content! %%i
Can you define further processing?
You can use a for loop to almost do this, but there's no easy way to insert CR/LF into an environment variable, so you'll have everything in one line. (you may be able to work around this depending on what you need to do.)
You're also limited to less than about 8k text files this way. (You can't create a single env var bigger than around 8k.)
Bill's suggestion of a for loop is probably what you need. You process the file one line at a time:
(use %i at a command line %%i in a batch file)
for /f "tokens=1 delims=" %%i in (file.txt) do echo %%i
more advanced:
for /f "tokens=1 delims=" %%i in (file.txt) do call :part2 %%i
goto :fin
:part2
echo %1
::do further processing here
goto :eof
:fin
To read in an entire multi-line file but retain newlines, you must reinsert them. The following (with '<...>' replaced with a path to my file) did the trick:
#echo OFF
SETLOCAL EnableDelayedExpansion
set N=^
REM These two empty lines are required
set CONTENT=
set FILE=<...>
for /f "delims=" %%x in ('type %FILE%') do set "CONTENT=!CONTENT!%%x!N!"
echo !CONTENT!
ENDLOCAL
You would likely want to do something else rather than echo the file contents.
Note that there is likely a limit to the amount of data that can be read this way so your mileage may vary.
Create a file called "SetFile.bat" that contains the following line with no carriage return at the end of it...
set FileContents=
Then in your batch file do something like this...
#echo off
copy SetFile.bat + %1 $tmp$.bat > nul
call $tmp$.bat
del $tmp$.bat
%1 is the name of your input file and %FileContents% will contain the contents of the input file after the call. This will only work on a one line file though (i.e. a file containing no carriage returns). You could strip out/replace carriage returns from the file before calling the %tmp%.bat if needed.
for /f "delims=" %%i in (count.txt) do set c=%%i
echo %c%
pause