Batch File: For Loop: Opens file instead of Rading it. Why? - batch-file

The code below works when the file name (i.e. links.txt) only is specified without quotes (might work with quotes, but I haven't tested it.).
When I substitute the filename for an entire file path, which also includes spaces, the batch file doesn't work the way it should. Instead, the text file is opened and when I close the text file, the cmd box then shows the message of Echo is off. It's like on the first instance of the loop it's opening the file. Why is this happening?
#echo off
SET var=
SETLOCAL EnableDelayedExpansion
FOR /f %%i in ('"Z:\My Docs\links.txt"') DO (
SET var=!var!%%i
)
echo !var!
ENDLOCAL
pause

for /f "usebackq" %%i in ("Z:\My Docs\links.txt") do ...
If you use single quotes around your file name, for command interprets you want to execute it, but with only double quotes, it is considered as a literal string.
From the for help on usebackq (see for /?): ... allows the use of double quotes to quote file names in file-set

Related

How to parse and echo multiple file paths using batch

I created a batch file that will echo or print the path of a file. Apparently, I am unable to print the path when I send multiple files as parameters to the said batch file.
#echo off
setlocal ENABLEDELAYEDEXPANSION
set string=%1
set string=!string:\=%%5C!
#echo %string% > D:\Playground\test.txt
Any help would be much appreciated. If there's anything unclear please let me know. Thanks.
Note: I send files to the batch file using the procedure below:
Right Click File
Send to
Choose the menu item that I created in sendTo that will pass the file to batch file
I don't know if this info helps but I didn't want to leave it out of my question.
%* will catch each input string passed separated by whitespace, enabledelayedexpansion should be used as you do set inside of a code block (). We also enclose the variables, including variable name with double quotes:
#echo off
setlocal enabledelayedexpansion
for %%a in (%*) do (
set "string=%%~a"
set "string=!string:\=%%5C!"
echo !string! >> D:\Playground\test.txt
)
As you can see, you need to use the for loop to iterate each of the input strings i.e %1 %2 and %3 etc.
As a Side note You can also drag and drop files onto the batch file to get results.
EDIT
Added the quote removal as requested set "string=!string:"=!" but note that using the strings as paths without quoting them will cause an issue in future if the paths contains whitespace.
To pipe to file without newline:
#echo off
setlocal enabledelayedexpansion
for %%a in (%*) do (
set "string=%%~a"
set "string=!string:\=%%5C!"
echo|set /p="!string! " >> D:\Playground\test.txt
)

Convert configuration file into variables and convert forward slash to backslash

I have a configuration file which I need for my bash script which has a layout:
A=C:/Example1/A
B=C:/Example2/B
C=C:/Example3/C
I want to use the same configuration file for my windows batch file. I need to convert the above file into variables which I have done using:
for /f "delims=" %%x in (test.txt) do (set "%%x")
How do I go about converting this file into variables while also converting all the forward slashes into backslashes?
Thanks!
add after your for line,
for /f "delims==" %%x in (q888.txt) do call set "%%x=%%%%x:/=\%%"
or, as a replacement for your existing for,
for /f "tokens=1*delims==" %%x in (q888.txt) do set "%%x=%%y"&call set "%%x=%%%%x:/=\%%"
(I used a file called q888.txt for testing)
The first smply executes a substitution, using a parsing trick. The second combines the set and substitution into one cascaded command by tokenising on = into %%x and %%y
This could be done with the following batch code:
#echo off
if not exist "test.txt" goto :EOF
setlocal EnableDelayedExpansion
for /F "usebackq tokens=1* delims==" %%I in ("test.txt") do (
if not "%%~J" == "" (
set "Value=%%~J"
set "Value=!Value:/=\!"
set "_%~n0_%%~I=!Value!"
)
)
echo The variables set from file are:
echo/
set "_%~n0_"
echo/
pause
endlocal
The batch file first checks if the file to process exists in current directory at all. The batch file processing is exited with a jump to predefined label EOF (end of file, requires enabled extensions which are enabled by default) in case of the file test.txt does not exist at all.
Next the file is read line by line with skipping empty lines and lines starting with a semicolon by command FOR which splits each line up into two strings.
The first string left of first equal sign is assigned to loop variable I. Everything right of first equal sign is assigned next loop variable J according to ASCII table.
The IF condition in the loop checks if a value is also defined for a variable. The value is assigned to an environment variable on which a string substitution is executed using delayed expansion to replace all / by \.
Then the modified value is assigned to an environment variable with a name starting with _, the name of the batch file, one more underscore and the string assigned to loop variable I read from the file.
For demonstration the variables with their values are finally output before the local variables are discarded on execution of last command ENDLOCAL.
I strongly recommend not assigning the values read from the file directly to environment variables whose name is completely also read from the file as this makes the batch file easy to manipulate by just modifying the contents of the text file. For example path=C:\Temp in text file would otherwise result in set "Path=C:\Temp" and from this point of batch file execution the running Windows command process would not find anymore any standard executable in directories defined by default in environment variable PATH like %SystemRoot%\System32.
A second variant which incorporates answer posted by Magoo with above batch code:
#echo off
if not exist "test.txt" goto :EOF
setlocal DisableDelayedExpansion
for /F "usebackq tokens=1* delims==" %%I in ("test.txt") do if not "%%~J" == "" set "_%~n0_%%~I=%%~J" & call set "_%~n0_%%~I=%%_%~n0_%%~I:/=\%%"
echo The variables set from file are:
echo/
set "_%~n0_"
echo/
pause
endlocal
The advantage of this variant is that delayed expansion is not needed for this solution which makes it possible to correct process also lines from file containing 1 or more exclamation marks on which first variant fails. And it is also a little bit faster, not noticeable faster for a human, but nevertheless a bit faster.
In both batch code blocks _%~n0_ can be replaced by (nearly) anything including also nothing although that is not recommended. Using just an underscore would be also possible as there are no environment variables defined by default by Windows which start with an underscore.
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 /? ... explains %~n0 (name of argument 0 - the batch file name - without path and without file extension).
echo /?
endlocal /?
for /?
goto /?
if /?
pause /?
set /?
setlocal /?
The simplest solution is to let the ~f FOR variable modifier put the full path in canonical form (including conversion of forward slashes to back slashes). I use the DELIMS and TOKENS options to split each line into the variable name and path so that I can apply the ~f to the path. It is important to use tokens=1* instead of tokens=1,2 just in case the path includes a = character.
for /f "delims== tokens=1*" %%A in (test.txt) do (set "%%A=%%~fB")
Note, however, that this strategy only works if your "test.txt" already contains full, absolute paths. If the file contains relative paths, then the ~f modifier will add drive and or folder values from the current directory to turn the relative path into an absolute path.

Using batch echo to write a vbe file (characters are not escaped)

So I'm currently writing a tutorial about security and for that reason I have to write a vbe file (encoded script written in VBScript) using a batch file.
So, I just have to write this to a file:
##~^mgAAAA==6 P3MDKDP"+k;:PH+XY~###&fks~D;EdO{6k^+SPhnk/Co8WX~~AMkYnm6ks+B~T+O|wmYtBPDn:a{2lDtS~6kxms{alY4~###&s+k/Con8K6~',h/T4GavJKndDJ~~8BPEwlDlV,2M.WMJbP###&2zEAAA==^#~#
(Note: There are some characters that cannot be printed above).
But the problem is that I never managed to write it successfully, I tried escaping all the characters using instructions from http://www.robvanderwoude.com/escapechars.php and it didn't work.
I tried using DelayedExpansion like this:
SET "foo=##~^mgAAAA==6 P3MDKDP"+k;:PH+XY~###^&fks~D;EdO{6k^+SPhnk/Co8WX~~AMkYnm6ks+B~T+O|wmYtBPDn:a{2lDtS~6kxms{alY4~###&s+k/Con8K6~',h/T4GavJKndDJ~~8BPEwlDlV,2M.WMJbP###^&2zEAAA==^#~# "
setlocal EnableDelayedExpansion
(
echo !foo!
) > test.vbe
And it did not work either, I have problems with characters that are not escaped.
Any ideas?? Thanks!!
The reason is obvious, that is a quotation mark after [...P3MDKDP]. Since you assign the variable "foo" to jumble characters with a open and a close quotation mark, like so SET "foo=...", batch think you stop assigning "foo" after [...P3MDKDP]. This leaves [+k;:PH+XY~.....] alone, without assigning to a variable or working with commands. Batch can't recognize it, and so the command prompt quit automatically.
What you can do is, assign the part after the quotation mark to another variable, I named it "foo2" in the following example:
#echo off
setlocal enabledelayedexpansion
SET "foo=##~^mgAAAA==6 P3MDKDP""
SET "foo2=+k;:PH+XY~###^&fks~D;EdO{6k^+SPhnk/Co8WX~~AMkYnm6ks+B~T+O|wmYtBPDn:a{2lDtS~6kxms{alY4~###&s+k/Con8K6~',h/T4GavJKndDJ~~8BPEwlDlV,2M.WMJbP###^&2zEAAA==^#~# "
echo !foo!!foo2!>test.vbe
pause >nul
And also, if you add another quotation mark before / after the quotation mark, like so [P3MDKDP ""], even though you did not assign the second part to a new variable, it still work, but it output an extra quotation mark in the string.
maybe this little trick helps you:
#echo off
for /f "delims=[]" %%n in ('find /n "REM DATA:" "%~dpnx0"') do set /a n=%%n
more +%n% "%~dpnx0">test.vbe
REM rest or your batchfile
goto :eof
REM DATA:
##~^mgAAAA==6 P3MDKDP"+k;:PH+XY~###^&fks~D;EdO{6k^+SPhnk/Co8WX~~AMkYnm6ks+B~T+O|wmYtBPDn:a{2lDtS~6kxms{alY4~###&s+k/Con8K6~',h/T4GavJKndDJ~~8BPEwlDlV,2M.WMJbP###^&2zEAAA==^#~#
(this trick avoids any character escaping or splitting the string. Can also be used to write a multiline text)

bat file: Use of if, for and a variable all together

Here goes:
I want to add text to a file if it exists. The text is to go on each line of the file at the very end. The text to be added is "Note: certain conditions apply"
I found syntax to check if the file exists, and syntax for a for loop to add text at the end of the line, but they do not seem to work at the same time in the bat file.
Also, advice varies about variable names, using "%" and using the quote marks themselves,
so here is what I have (assume everything takes place in the same directory)....
#echo off
setLocal EnableDelayedExpansion
PAUSE
REM File to be modified -- 1
SET FileToModify1=abcd.txt
SET SaveFile1=abcd1.txt
PAUSE
IF EXIST "%FileToModify1%" (
echo Yes
)
IF EXIST "%FileToModify1%" (
for /f "tokens=* delims= " %%a in "%FileToModify1%" do (
echo %%a Note: certain conditions apply >> "%SaveFile1%"
)
)
PAUSE
Does anyone have a suggestion on what to do here?
Also, is it better to have quotes around abcd.txt or not?
Why all the mysterious "%" around variables?
Please also see loop through file saving to variable for a much more efficient solution to the same problem....
You need this (works):
for /f "tokens=* delims= " %%a in (%FileToModify1%) do (
Where you have (doesn't work, wrong syntax):
for /f "tokens=* delims= " %%a in "%FileToModify1%" do (
From the online help (via for /?)
For file names that contain spaces, you need to quote the filenames with
double quotes. In order to use double quotes in this manner, you also
need to use the usebackq option, otherwise the double quotes will be
interpreted as defining a literal string to parse.
Also, is it better to have quotes around abcd.txt or not?
It's required if your file name has spaces, otherwise it's optional.Your file name doesn't have spaces so I used the simpler approach, no quotes.
Why all the mysterious "%" around variables?
Well it doesn't have to be "mysterious". Here's an example, from the command line:
> set fname=MyFile.txt
> echo %fname%
MyFile.txt
The %'s around the variable name are seen by the shell and trigger the variable expansion. To see the online help, type set /?, and you'll get more details than you can stand.

batch file changing double quote

Having trouble running a batch file.
SET startIN="D:\Documents and Settings\%USERNAME%\Desktop\DataXfer Helper\StartFolder"
SET collection="D:\Documents and Settings\%USERNAME%\Desktop\DataXfer Helper\StartFolder\*.zip"
FOR /F %%G IN (‘dir /b %collection%\*.zip’) DO “C:\Program Files\Winzip\wzunzip” –E %startIN%\%%G %startIN%
When I type the line at the command prompt - it works fine (the only difference is when typed at the command prompt I use %G instead of %%G).
So, the environement variables are being created properly - but when I run the batch, the single quotes and the hyphen before the E are being turned into other characters (can't identify what they are).
So, any ideas why running the batch would change the characters?
Thank you.
There are a couple of problems:
The symbols in your FOR line are not supported ASCII chars. Retype the ', ", and - in the command line to correct them.
The string expansion is going to include the quotes you set in the path above. For example, %startIN%\%%G will expand to "D:\Documents and Settings\%USERNAME%\Desktop\DataXfer Helper\StartFolder"\MyFile.zip. When dealing with paths, make sure your logic is aware of quotes so they don't get trapped in the middle of the result.
Try updating your script to this:
REM Remove the quotes from the path.
REM Quotes will be added once we know the full path.
SET startIN=D:\Documents and Settings\%USERNAME%\Desktop\DataXfer Helper\StartFolder
REM Quote here because we know the full path.
SET collection="%startIN%\*.zip"
REM Update FOR loop to include parsing options and properly quote output.
REM Also update invalid ASCII chars.
FOR /F "usebackq tokens=* delims=" %%G IN (`dir /b %collection%`) DO "C:\Program Files\Winzip\wzunzip" -E "%startIN%\%%G" "%startIN%"

Resources