How to handle space of Filename in Batch For Loop - for-loop

#echo off
echo processing please wait...
setlocal enabledelayedexpansion
set txtfile=%~dp0mysql\my.ini.bak
set newfile=%~dp0mysql\my.ini
if exist "%newfile%" del /f /q "%newfile%"
for /f "tokens=*" %%a in (%txtfile%) do (
set newline=%%a
echo !newline! >> %newfile%
)
Now my.ini.bak file is in D:\Program Files\my.ini.bak
Error : The system cannot find the file Files\mysql\my.ini.bak.
How to make this code work, so it copy each line from my.ini.bak to my.ini

The space in the path is indeed preventing FOR /F from opening the file successfully. You need quotes around the file name, but then you also need the FOR /F "USEBACKQ" option so that the quoted name is treated as a file name instead of a text string.
Using "TOKENS=*" is almost, but not quite the same as "DELIMS="
"DELIMS=" preserves the entire line
"TOKENS=*" preserves the remainder of the line after first stripping any leading spaces and/or tabs
I generally prefer "DELIMS=" unless I have a reason to strip leading spaces.
If there is a chance that the .INI file can contain ! character then you will want to toggle delayed expansion on and off within the loop. The value of %%a will be corrupted if it contains ! and delayed expansion is enabled.
It is more efficient to enclose the entire FOR loop within another set of parens and redirect the output just once instead of once for each iteration. It also eliminates the need to first delete the file if it already exists.
#echo off
echo processing please wait...
setlocal disableDelayedExpansion
set "txtfile=%~dp0mysql\my.ini.bak"
set "newfile=%~dp0mysql\my.ini"
>"%newfile%" (
for /f "usebackq delims=" %%a in ("%txtfile%") do (
set newline=%%a
setlocal enableDelayedExpansion
rem Presumably more processing goes here
echo !newline!
endlocal
)
)

I don't think you need to quote the paths, you can just use the short names in the expanded path. So use %~dps instead of %~dp
#echo off
echo processing please wait...
setlocal enabledelayedexpansion
set txtfile=%~dps0mysql\my.ini.bak
set newfile=%~dps0mysql\my.ini
if exist "%newfile%" del /f /q "%newfile%"
for /f "tokens=*" %%a in (%txtfile%) do (
set newline=%%a
echo !newline! >> %newfile%
)
By the way, the error I get with your original code is slightly different from your error, not sure why.
The system cannot find the file C:\Program.

The problem is the space in the file paths. I can't test this right now, but believe quoting the paths will fix it:
set txtfile="%~dp0mysql\my.ini.bak"
set newfile="%~dp0mysql\my.ini"
Here is the full code I tested with. For testing I added a space in "my sql" and created a folder by this name.
#echo off
echo processing please wait...
setlocal enabledelayedexpansion
set txtfile="%~dp0my sql\my.ini.bak"
echo %txtfile%
set newfile="%~dp0my sql\my.ini"
echo %newfile%
if exist "%newfile%" del /f /q "%newfile%"
for /f "tokens=*" %%a in (%txtfile%) do (
set newline=%%a
echo !newline! >> %newfile%
)

Related

How to prevent empty space lines while iterating a .txt file using FOR loop in batch Script

I have one .txt file with text and some empty space lines. While doing some operations in .txt file by using for loop, found originally contained empty space lines are gone.
Example :
I have a temp.txt file with below input :
#
Require
#
#Rel task
#
HOST_ID=
ACTIVATE_ID
#
#
After doing some operations using FOR Loop I am getting result in same .txt file like below :
#
Require
#
#Rel task
#
HOST_ID=56767\Ether
ACTIVATE_ID
#
#
So, I don't want to ignore those empty space lines.
I tried to use usebacq keyword in for loop, but not working.
I tried each and possible way to do this, but failed everytime.
Here, is my code :
#echo off
setlocal enableextensions disabledelayedexpansion
set rem=56767\Ether
set "textFile=temp.txt"
for /f "delims=" %%i in ('type "%textFile%" ^& break ^> "%textFile%" ') do (
set "line=%%i"
setlocal enabledelayedexpansion
if !line!==HOSTID= (
set "foo=!line:HOSTID=HOSTID=%rem%!"
set "line=!foo:~0,-1!"
)
>>"%textFile%" echo(!line!
endlocal
)
:EXIT
pause
In above code, I am doing to append some extra string in front of provided string in same .txt file.
Here's an alternative method, the idea being that you don't need delayed expansion, and, (for safety), you're not trying to read from and write to the same file.
What it does is to first determine if your required string exists in the file, if it doesn't the script closes, if it does it sets a variable to its line number. Then the file is parsed outputting the contents of each line untouched except for the line matching the saved variable, where it appends %rem% to it.
When the script ends your original file should exist along side it with a .bak extension.
#Echo Off
SetLocal EnableExtensions
Set "rem=56767\Ether"
Set "textFile=temp.txt"
Set "lineNum="
For /F Delims^=: %%G In ('^""%__AppDir__%findstr.exe" /INR "\<HOST_ID=\>" "%textFile%" 2^>NUL^"')Do Set "lineNum=%%G"
If Not Defined lineNum GoTo :EOF
For %%G In ("%textFile%")Do Set "_=%%~nG.bak" & Copy /Y "%%G" "%%~nG.bak">NUL
(For /F "Tokens=1*Delims=:" %%G In ('^""%__AppDir__%findstr.exe" /N "^" "%_%"^"')Do If %%G NEq %lineNum% (Echo=%%H)Else Echo %%H%rem%)>"%textFile%"
Pause
I am not sure if your file has a space before HOST_ID= like it currently does, but both with/without space has been added in this example:
#echo off
setlocal enableextensions disabledelayedexpansion
set "rem=56767\Ether"
set "textFile=temp.txt"
for /f "tokens=1,* delims=[]" %%i in ('type "%textFile%" ^| find /v /n "" ^& break^>"%textFile%"') do (
set "line=%%j"
setlocal enabledelayedexpansion
if "!line!" == "HOST_ID=" set "line=!line!%rem%"
if "!line!" == " HOST_ID=" set "line=!line!%rem%"
echo(!line!
endlocal
)
:EXIT
pause
Delimiters are [] because we add line numbers which you do not see as [n] before each entry by using find /V /N "". This way we retain the empty lines.

Swap tokens of a file name using batch file

I have file(s) in a folder with names like "223.DAT_2017010211315" I want to loop through all the files and rename them to like 223_2017010211315.DAT"
The closest I got to this requirement is as follows. I could just get the first token of the file name.
set "res=223.DAT_2017010211315"
for /f "tokens=1 delims=." %%i in ("%res%") do (set prefix=%%i)
echo %prefix%
pause
Could someone help me through this?
Let's start by iterating the file system. This should search the required files and show them
for %%f in ("*.dat_*") do echo %%f
Now, once we are able to find the files to process we need to separate the name and the extension of the files. That is an easy task as the for replaceable parameters (%%f in previous code) allow the usage of some modifiers to retrieve specific information of the referenced file (see for /? for a full list). We will use %%~nf (the name of the file referenced by %%f) and %%~xf (the extension of the file being referenced by %%f)
for %%f in ("*.dat_*") do echo %%~nf %%~xf
Once we have the two elements, we need to split the extension using the underscore as a delimiter. This will give us two tokens, left and right sides of the underscore. For this for /f is used to process the file extension.
for /f "tokens=1,2 delims=_" %%a in ("%%~xf") do echo %%a %%b
As we are requesting two tokens, the for /f will use the requested replaceable parameter %%a to store the first one, and will create an additional replaceable parameter %%b (next character) to store the second token.
%%~nf %%~xf
[.][................]
223.DAT_2017010211315 = %%f
^..^ ^...........^
%%a %%b
So, for each file in the list, execute the for /f to retrieve the needed information to execute the ren command.
for %%f in ("*.dat_*") do for /f "tokens=1,2 delims=_" %%a in ("%%~xf") do (
echo ren "%%f" "%%~nf_%%b%%a"
)
Note that for debugging purpouses, the ren command is not executed, only echoed to console to check the code behaviour. If the output is correct, remove the echo and run the code again.
#echo off
REM for every file matching the filter do:
for %%f in (*.dat_*) do (
REM disassemble into tree tokens, using . and _ as delimiters:
for /f "tokens=1,2,3 delims=._" %%a in ("%%~f") do (
REM re-assemble in different order:
echo %%a_%%c.%%b
)
)
Just to show an alternative way:
#echo off&setlocal enabledelayedexpansion
pushd "X:\path\to\folder"
for %%A in (*.dat_*) do (
set fname=%%A
Echo ren "%%A" "!fname:.DAT=!.DAT"
)
Popd
If output looks ok, remove the echo

Reading a file with for statment - Batch

I have this code:
#echo off
for /f "delims=" %%a in ("%~dp0\files\text\lead_r.txt") do set /p key= < lead_r.txt
ECHO %key%
PAUSE
What I want it to do is to open a specific text file, read it and then write what's in it to %key%. It works when lead_r.txt and the batch file are in the same folder but it fails when I move lead.txt to \files\text. There are no files with spaces in \files\text so i don't know where the problem is.
Thanks
Hard to understand your goal, but try next code snippet:
#echo off >Nul
setlocal EnableDelayedExpansion
for /f "delims=" %%a in ("%~dp0\files\text\lead_r.txt") do (
rem the same file in next line
rem set /p key=< lead_r.txt
set /p key= < %%a
ECHO !key!
PAUSE
)
endlocal
Here mind EnableDelayedExpansion keyword of setlocal command = Expand variables at execution time rather than at parse time, if used !key! syntax instead of %key% one.

Not looping through all the files

Windows batch script:
I have three files in a drectory.I`m trying to loop through the multiple files located in the directory and rename the files,but some how its not looping through.
i can see that the var1 is getting the right file name but not for sub1.This in turn renames the other two files in the directory with wrong output. Could some one please help me on this.
#echo on & setlocal EnableDelayedExpansion
set a=9
for /f "tokens=*" %%i in ('dir /b "C:\XX\YY\ZZ*"') do (
set var1=%%i
SET sub1=%var1:~7,22%
ECHO %sub1%
ren "%%i" "ABC!sub1!_!a!.dat"
set /a a+=1
)
#echo on
setlocal EnableDelayedExpansion
set a=10001
for /f "tokens=*" %%i in ('dir /b "C:\TEST\PBM\PAR*"') do (
set var1=%%i
SET sub1=!var1:~7,22!
ECHO !sub1!
ECHO ren "%%i" "ABC!sub1!_!a!.dat"
set /a a+=1
)
With delayedexpansion any reference to the value of a variable that is changed within the loop must use the !var! syntax. %var% will access the parse-time value.
Note: REN is now echoed for verification.

How can I edit this so it works with files that have spaces?

#echo off
set /A Counter=0
setlocal enabledelayedexpansion
for %%D in ("e:\test test\") do (
for /f %%F in ('dir /a-d /b %%D*.*') do (
ECHO.
ECHO Current file is: %%F
set src=%%F
set dest="e:\test test\space locate\%%F"
if not exist !dest! move !src! !dest!
if exist !dest! (
ECHO.
ECHO ERROR: "%%F" already exists
set /A Counter+=1
)
ECHO source file is !src!
ECHO destination is !dest!
)
)
echo.
echo %Counter% files not moved.
You probably just need to put quotes (") around all your filenames.
I'm talking about this sort of thing:
if not exist "!dest!" move "!src!" "!dest!"
That's just a suggestion, I don't have time to actually try to debug it right now.
Edit in response to comment:
for by default uses spaces as delimiters. You should say for /f "delims=" instead of just for /f in order to tell it not to do that.

Resources