I have a script which will check if the file names and the content of the files are same or not, below is the code and it is working fine
ECHO OFF
CLS
for %%i in (C:\Users\f1ym41a\Documents\deep\*.DAT) do (
fc C:\Users\f1ym41a\Documents\deep\MOVE.DAT %%i > NUL
if errorlevel 1 (
CALL :error
echo C:\Users\f1ym41a\Documents\deep\MOVE.DAT and %%i are different >>output.log
) ELSE (
CALL :next
echo C:\Users\f1ym41a\Documents\deep\MOVE.DAT and %%i are same >>output.log
)
timeout 5
)
PAUSE
What i need to do is if the file names are same then it will change the flag in the ini file to 1. Below is the ini file (deep.ini)
[INI]
flag = 0
Since i am new to batch scripting. Can somebody help me out with this?
You can try with replacer.bat:
call replacer.bat move.dat "flag = 0" "flag = 1"
This is an easy to achieve task with using JREPL.BAT written by Dave Benham which is a batch file / JScript hybrid to run a regular expression replace on a file using JScript.
#echo off
if not exist "%USERPROFILE%\Documents\deep\MOVE.DAT" goto :EOF
if not exist "%~dp0jrepl.bat" goto :EOF
call "%~dp0jrepl.bat" "^(flag *= *)0" "$11" /F "%USERPROFILE%\Documents\deep\MOVE.DAT" /O -
The batch file first checks if the file to modify exists at all and immediately exits if this condition is not true, see Where does GOTO :EOF return to?
The batch file JREPL.BAT must be stored in same directory as the batch file with the code above. For that reason the batch file checks next if JREPL.BAT really exists in directory of the batch file and exits if this condition is not true.
The meaning of the regular expression search string is:
^ ... find at beginning of a line
(...) ... a string referenced in replace string with $1 to keep this part of found string unmodified
flag ... case-sensitive the string flag
* ... with 0 or more spaces
= ... and an equal sign
* ... and once more 0 or more spaces
0 ... and the character 0.
The replace string back-references the found string between beginning of line and character 0 with $1 and replaces 0 by 1.
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 also %~dp0 ... drive and path of argument 0 which is the batch file path always ending with a backslash.
echo /?
goto /?
if /?
jrepl.bat /?
:: 1st need remove some possible space in the string to got more precision
when compare them: "flag = 0" will became "flag=0", no
space and no tab.
:: 2nd for to do this, use this "' (2 characters) to set a variable that
use "=" to string instead a special character,
by set "'=flag=0" (very old technical!)
:: 3rd treat equal, treat tab character, and to remove it, because some time
this is a invisible and possible character that can eventually occur
in file dat, see in this question 10878138
:: 4th Compare the strings by string from file by file, line by line...
:: finely You need replace line in the file (.dat or .ini) this part I´m really confuse, but the code are above, sorry if my error!
Obs: use the conversion of this "flag = 0" this this one "flag=0", only for processing comparatives operation, wend the %%i match flag = 0 then only changed to replace to files by flag = 1, bat, a specific thing here is the command fc are comparing %%i, by the same file in looping for with no other file.
#echo off && setlocal EnableExtensions EnableDelayedExpansion
set "'=flag=0"
set _file_new_flag1="%temp%\Flag1.dat"
set _path_to_dats=C:\Users\f1ym41a\Documents\deep\
for /f "delims= " %%T in ('forFiles /p "." /m "%~nx0" /c "cmd /c echo(0x09"') do set "_tab=%%T"
type nul >output.log && set "_tab=%_tab:~0,1%"
cd /d "!_path_to_dats!"
for /f "tokens=* delims= " %%x in ('dir /o-d /on /b "*.dat"') do (
if defined _file_new_flag (
move /y "!_file_new_flag1!" "!_file_now!"
set _file_now=<nul
set "_file_now=%%~x"
) else (
set "_file_now=%%~x"
)
call :_file_compare_:
)
endlocal & goto :_end_of_file_:
:_file_compare_:
for /f "tokens=* delims= " %%X in ('type "!_file_now!"') do (
for /f "tokens=* delims= " %%i in ('echo/"%%~X"') do (
set "_to_compare=%%~i"
call set "_to_compare=!_to_compare: =!"
for /f "tokens=* delims=" %%I in ('echo/%_tab%') do call set "_to_compare=!_to_compare:%%I=!"
if ["!_to_compare!"] equ ["%'%"] (
echo/C:\Users\f1ym41a\Documents\deep\MOVE.DAT and %%i are same >>output.log
echo/%%~i>>!_file_new_flag1!
) else (
echo/C:\Users\f1ym41a\Documents\deep\MOVE.DAT and %%i are different >>output.log
echo/flag = 1>>!_file_new_flag1!
)
timeout /t 5
set _to_compare=<nul
)
)
exit /b
:_end_of_file_:
So sorry about my English.
Related
I have written small script for converting text to uppercase as shown below and saved this file as .BAT extension
`converttoupper.bat`
I want user to try "help" command, so that they get the help on syntax for using the commands as shown below
help converttoupper
something like this
# help converttoupper
For more information on a specific command, type HELP command-name
CONVERTTOUPPER This converts the text to upper case
Update
I am fine even if I get something as shown below. I do not want to overwrite any windows command.
helpme converttoupper
or
helpme connectvpn
I have many BAT files, and wish to display respective helps when each executed.
You can create a "fake" function. Let's call this define.cmd and place it in %systemroot%\system32
We add the code:
#echo off
for /f "tokens=1,*delims=? " %%i in ('type "%~1" ^|findstr ":?"') do echo %%j
Then in all your batch files you want people to read the help for, add the help lines by starting them off with a :? using your convertoupper.cmd file as example:
#echo off & set upper=
if "%~1" == "" echo incorrect usage & call define.cmd "%0"
if "%~1" == "/?" call define.cmd "%0"
for /f "skip=2 delims=" %%I in ('tree "\%~1"') do if not defined upper set "upper=%%~I"
set "upper=%upper:~3%"
echo %upper%
goto :eof
:? # help converttoupper
:? "define %0" or "%0 /?" will display this help content
:? For more information on a specific command, type HELP command-name
:? CONVERTTOUPPER This converts the text to upper case
Now you can run define converttoupper or converttoupper /?. If you run converttoupper without any arguments, it will also display the same help.
Below is an example of safely handling arg capture and help enqueries.
After arguments are safely Captured, Findstr is used to test the content for valid help switches:
Set Args | %SystemRoot%\System32\Findstr.exe /bli "Args=\/? Args=-? Args=Help?" > nul && (Rem commands)
Set Args : allows the argument string to be piped to findstr without any risk of failure due to poison characters.
/bli : findstr sawitches : match literal string at beginning of line ignoring case.
"Args=\/? Args=-? Args=Help?" : Space delimited list of strings to match; treated as match string a or b or c
> nul : Suppress the output of any match
&& : Conditional operator; 'On command success'
Note: Terminating each help switch with ? allows use of substring modification to remove the leading switch and space and directly Call a label prefixed with the query keyword
#Echo off & SETLOCAL
=========================================================================
Rem -- Arg capture method is a modified version of Dave Benhams method:
Rem -- https://www.dostips.com/forum/viewtopic.php?t=4288#p23980
SETLOCAL EnableDelayedExpansion
1>"%~f0:Params.dat" <"%~f0:Params.dat" (
SETLOCAL DisableExtensions
Set prompt=#
Echo on
For %%a in (%%a) do rem . %*.
Echo off
ENDLOCAL
Set /p "Args="
Set /p "Args="
Set "Args=!Args:~7,-2!"
#Rem duplicate Args for the purpose of counting doublequotes [destructive].
Set "DQcount=!Args!"
) || (
Echo(%~nx0 requires an NTFS drive system to function as intended.
CMD /C Exit -1073741510
) || Goto:Eof
If Not defined Args Goto:NoArgs
REM substitute doublequotes in Args clone 'DQcount'; count substring in string;
REM assess if count is even; If false "||": Remove doublequotes from string. If true "&&" and if entire
REM arg line is doublequoted, remove outer quotes.
Set Div="is=#", "1/(is<<9)"
Set "{DQ}=0"
Set ^"DQcount=!DQcount:"={DQ}!"
2> nul Set "null=%DQcount:{DQ}=" & Set /A {DQ}+=1& set "null=%"
Set /A !Div:#={DQ} %% 2! 2> nul && Set ^"Args=!Args:"=!" || If [^%Args:~0,1%^%Args:~-1%] == [""] Set "Args=!Args:~1,-1!")
For /f Delims^= %%G in ("!Args!")Do Endlocal & Set "Args=%%G" 2> nul
:NoArgs
=====================================================================
Rem help query assessment
(
Set Args | %SystemRoot%\System32\Findstr.exe /bli "Args=\/? Args=-? Args=Help?" > nul && (
Rem Args value has leading /? -? or help?
If not "%Args:*?=%"=="" (
Rem Args value contains leading /? -? or help? with additional Parameter
Call:%Args:*? =%_Syntax && Goto:Eof || (
Rem quit after Call to Syntax info if valid Parameter; else notify invalid and show valid syntax queries.
Echo(Invalid query: "%Args:*? =%" : Does not Match a valid Help Query:
)
)
Rem show valid syntax queries.
For /F "Tokens=1 Delims=:_" %%G in ('%SystemRoot%\System32\Findstr.exe /R "^:.*_Syntax" "%~f0"') Do Echo(%~nx0 /? %%G
ENDLOCAL & Exit /b 0
)
) 2> nul
Set Args
Goto:Eof
Rem Demo syntax labels
:Demo_Syntax
Echo %~0 help info
Exit /b 0
:Example_Syntax
Echo %~0 help info
Exit /b 0
I'm trying to parse a .txt file using batch script, line by line, untill I find "arg =" string and then get the following number. To put it into context, I'm trying to parse this gdb.txt file
warning: No executable has been specified and target does not support
determining executable automatically. Try using the "file" command.
0x00007c2c in ?? ()
Loading section .sec1, size 0x20000 lma 0x0
Start address 0x8560, load size 131072
Transfer rate: 103 KB/sec, 1110 bytes/write.
Command Executed successfully: semihosting enable
Breakpoint 1 at 0x790a: file C:\LMA\ws_new\wam_sdk1886.31.001.1C_ver1\src\sdk\wam\bsp\detail/exit.c, line 21.
Note: automatically using hardware breakpoints for read-only addresses.
Breakpoint 1, exit (arg=0) at C:\LMA\ws_new\wam_sdk1886.31.001.1C_ver1\src\sdk\wam\bsp\detail/exit.c:21
21 volatile std::uint8_t a = 0;
arg = 0
[Inferior 1 (Remote target) detached]
I've come up with these few lines of batch script:
#echo off
for /f delims^=^ eol^= %%A in (gdb.txt) Do (
echo %%A
findstr /c:"arg =" %%A>nul 2>nul
echo %errorlevel%
)
I would like the script to recognize the line with "arg =" so I can read 0 afterwards.
However this script seems not to be able to recognize "arg =" and always prints %errorlevel% as 1.
What am I missing here?
It's much easier to filter the file for the wanted line instead of searching through each line (and much faster, especially with big files):
for /f "tokens=2 delims== " %%A in ('type gdb.txt^|findstr /bic:"arg = "') Do set "var=%%A"
echo arg is %var%.
Note: should there be more than one matching line, this will give you the last result.
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q64803488.txt"
SET "arg="
FOR /f "usebackq tokens=1-3" %%a IN ("%filename1%") DO (
IF /i "%%a"=="arg" IF "%%b"=="=" SET "arg=%%c"
)
ECHO arg found was "%arg%"
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances. The listing uses a setting that suits my system.
I used a file named q64803488.txt containing your data for my testing.
The usebackq option is only required because I chose to add quotes around the source filename.
Set arg to empty to ensure it isn't already set.
For each line in the file, tokenise using the default delimiter set (which includes space) and select the first 3 tokens. If the first (%%a) is arg (/i to make case-insensitive) and the second in %%b is = then assign the third (%%c) to arg.
If I was doing this in a batch-file, I'd do it like this:
#For /F Tokens^=* %%G In ('%SystemRoot%\System32\findstr.exe /BIRC:"arg = [0123456789]" "gdb.txt" 2^> NUL') Do #Set /A %%G 2> NUL
#Set arg & Pause
The second line is there just to show you the results. You should replace that with your own code.
The first line could possibly be made shorter too, (although I wouldn't recommend it)!
#For /F Tokens^=* %%G In ('FindStr /BIRC:"arg = [0-9]" gdb.txt')Do #Set /A %%G
I have file C:/test.txt which is having content as below.
05/13/2017 07:29:34 Value= \\america.com\efpf_share\efpf\ipm_files
05/13/2017 07:29:41 Value= \\america.com\efpf_share\efpf\ipm_files
05/17/2017 08:31:54 Value= \\america.com\efpf_share\efpf\ipm_files
05/17/2017 08:32:03 Value= \\america.com\efpf_share\efpf\ipm_files
I want to extract 'epfp' or any string comes at this place and convert this into upaercase also if its have test attached (as epfptest) then it it should split EPFP-TEST. For extracting I am running the below code and redirecting the output in temp1.txt file
findstr "Value=" C:\test.txt| findstr america > "C:\temp.txt" && for /l %l in (1,1,1) do #for /f "tokens=3* delims=." %a in ('findstr /n /r "^" "C:\temp.txt" ^| findstr /r "^%l:"') do #echo %b > c:\temp1.txt
now temp1.txt file having the content as below :
com\efpf_share\efpf\ipm_files
Now finally I am exracting efpf from below code it gives me the output as below :
for /f "tokens=3 delims=\" %a in (c:\temp1.txt) do #echo %a
epfp
I want this output or to be converted as EPFP (in uppercare) and if this output does not having test string attached then it should only split as EPFP-TEST
Note: Final output can be anything (in this case epfp) and I want this convert in uppercase also if this output containing 'test' string attached then that should be split in "STRING-TEST"
This test file modification task should be definitely not done using a batch file and pure Windows command processor commands. There are much better scripting languages for this task.
It would be also much more useful to do this file content modification with a powerful text editor like UltraEdit or any other text editor with Perl regular expression support. Searching for (\\[^\\]+\\)(?=ipm_files) and using as replace string \U$1\E changes the directory name left to ipm_files to upper case and searching for (?<!\\|-)TEST(?=\\ipm_files) and using as replace string -TEST inserts the hyphen character left to TEST if there is not already a hyphen and the entire folder name is not TEST.
However, here is a commented batch file solution for this task:
#echo off
if not exist "%~dp0Test.txt" goto :EOF
setlocal EnableExtensions DisableDelayedExpansion
set "Modified=0"
set "DataFile=%~dp0Test.txt"
set "TempFile=%TEMP%\%~n0.tmp"
del "%TempFile%" 2>nul
for /F delims^=^ eol^= %%I in ('%SystemRoot%\System32\findstr.exe /N "^" "%DataFile%" 2^>nul') do (
set "Line=%%I"
call :ProcessLine
)
if %Modified% == 1 move /Y "%TempFile%" "%DataFile%"
del "%TempFile%" 2>nul
endlocal
goto :EOF
rem The subroutine ProcessLine removes first line number and colon inserted
rem by FINDSTR at beginning of each line to process correct also empty lines
rem in data file. The subroutine jumps to output of line in case of current
rem line is an empty line.
rem Next the line is split up into substrings using backslash as delimiter.
rem Of interest are only the fourth and fifth substrings. The fifth substring
rem should be ipm_files to identify the current line as a line to process.
rem A jump to writing the line into temporary file is done if this condition
rem is not true. Otherwise the fourth substring is assigned to a variable
rem because that string is the folder name to modify by this batch file.
rem Each ASCII character in the folder name is replaced by its upper case character.
rem If the entire new folder name is TEST, just do the replace and don't change
rem the folder name to -TEST. If the new folder name ends already with -TEST,
rem just do the replace. But if new folder name ends with only TEST, replace
rem just TEST by -TEST with hyphen.
rem A case-sensitive comparison of current and new folder name is done before
rem running the folder replace on line to determine if the replace is really
rem necessary at all. The modification information is saved in an environment
rem variable which is passed over local environment of subroutine to main code
rem above. This information is used finally to determine if the data file must
rem be replaced at all by the temporary file because of a modification is made
rem or the temporary file can be simply deleted as being equal with data file.
:ProcessLine
setlocal EnableDelayedExpansion
set "Line=!Line:*:=!"
if not defined Line goto WriteLine
for /F "tokens=4,5 delims=\" %%A in ("!Line!") do (
if /I not "%%B" == "ipm_files" goto WriteLine
set "CurFolderName=%%A"
)
set "NewFolderName=%CurFolderName%"
for %%C in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) do set "NewFolderName=!NewFolderName:%%C=%%C!"
if "%NewFolderName%" == "TEST" goto DoReplace
if "%NewFolderName:~-5%" == "-TEST" goto DoReplace
if "%NewFolderName:~-4%" == "TEST" set "NewFolderName=%NewFolderName:~0,-4%-TEST"
:DoReplace
if "%CurFolderName%" == "%NewFolderName%" goto WriteLine
set "Modified=1"
set "Line=!Line:%CurFolderName%\ipm_files=%NewFolderName%\ipm_files!"
:WriteLine
echo(!Line!>>"%TempFile%"
endlocal & set "Modified=%Modified%"
goto :EOF
%~dp0Test.txt must be two times replaced by real file name of data file with relative or absolute path.
The purpose of first FOR loop in main code at top is described in my answer on:
How to read and print contents of text file line by line?
The other command lines are explained by the remarks between main code and subroutine.
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 /?
del /?
echo /?
endlocal /?
findstr /?
goto /?
if /?
move /?
rem /?
setlocal /?
I would like to create a batch file that will search in a dir for all .pdf files that have a name of 10 characters as we have many .pdf's with different characters in name so I need to sort them out and move (cut and paste) them to a 2nd directory that is prepared. Can you please help me with this batch file?
example
setdir test contain .pdfs
--+6570296402-1-982464371-120.pdf
+6581239585-1-982470028-120.pdf
5710101306.pdf
0-PZ-6562825.pdf
0-PZ-545515247-1-982466351-120.pdf
5455152471.pdf
result:
target dir - test2 - where need to be moved .pdf with 10 characters
5710101306.pdf
5455152471.pdf
etc
Thank you so much
Running from the current directory you could probably do this using Where and Move:
#Echo Off
For /F "Delims=" %%A In ('Where/F .:??????????.pdf'
) Do Move /Y %%A "Test2">Nul
(for /f "delims=" %%a in ('dir /b /a-d *.pdf') do call :select10 "%%a") >filename.txt
... more processing if required
goto :eof
:select10
set "name=%~n1"
set "name=%name:~9%"
if not defined name goto :eof
set "name=%name:~1%"
if not defined name echo %~1
goto :eof
This should solve the problem.
perform a dir list of *.pdf, selecting filenames only. Pass the filename found to subroutine :select10, in quotes in case of spaces in filename.
The subroutine set name first to the name part of the filename received, then removes the first 9 characters. If the result is an empty variable, skip to end-of-file. If not, select all but the first character. If the result is not an empty string, the name must be 11 or more characters - if it's empty, then echo the name passed in the first instance.
The parentheses around the for command will cause the echoed data to be accumulated into the file nominated.
If you want to move the file to the destination, not simply list the selections, remove the ( before the for, and the ) >filename.txt after and replace the echo with move "%1" destination\
You could also do the same without using a subroutine as:
for /f %%a in ('dir /b /a-d *.pdf') do (
set "name=%%~na"
setlocal enabledelayedexpansion
set "name=!name:~9!"
if defined name (
set "name=!name:~1!"
if not defined name move "%%a" destination\
)
endlocal
)
Using delayed expansion to process the substringing operations.
I have the following batch script to read an xml file and find a word (in this case, "factory"):
#echo off & setlocal enabledelayedexpansion
for /f "delims=" %%a in ('findstr /C:"factory" xcsconfig.xml') do set content=%%a
set content=%content:*"=%
set content=%content:~0,-1%
echo %content%
exit /b
Here's part of the xml file:
<loggers>
<recorder1>
<add name="factory" value="xlog"/>
<add name="alias" value="WSEnterprise.log"/>
</recorder1>
<recorder2>
<add name="factory" value="weblog"/>
</recorder2>
</loggers>
The code works fine and will always return the "first" founding - value="weblog"/. My question is, is there a way to return the founding under a specific tab? (i.e. I want to search specific under recorder1 instead of record2 tab, and return answer value="xlog"/). Thanks in advance.
EDIT: I changed my expected answer, it was incorrect
#ECHO Off
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sectionstart=recorder1"
SET "insection="
for /f "delims=" %%a in ('type q25062317.txt') do (
IF DEFINED insection (
ECHO "%%a"|FINDSTR /c:"factory" >NUL
IF NOT errorlevel 1 SET "content=%%a"
)
ECHO "%%a"|FINDSTR /i /L /c:"<%sectionstart%>" > NUL
IF NOT ERRORLEVEL 1 SET insection=Y
ECHO "%%a"|FINDSTR /i /L /c:"</%sectionstart%>" > NUL
IF NOT ERRORLEVEL 1 SET "insection="
)
set content=!content:*"=!
set content=!content:*"=!
set content=!content:~1,-1!
echo %content%
GOTO :EOF
I used a file named q25062317.txt containing your data for my testing.
You can incorporate also the next statements inside the do block of the for cycle. I mean:
setlocal EnableDelayedExpansion for /f "delims=" %%a in ('findstr /C:"factory" xcsconfig.xml') do (
set content=%%a
set content=!content:*"=!
set content=!content:~0,-1!
echo !content!
)
In this way the output is not only the last XML code line but all the code lines that contain the "factory" string in the file considered. Of course this example doesn't echo only a single desired string but this is possible setting a condition to the output of the loop.
Here is a robust tool that can help you - the command looks like this to get the line you need and it can be wrapped in a for /f loop.
type file.xml |findrepl "<recorder1>" /e:"</recorder1>" /b:"factory"
This uses a helper batch file called findrepl.bat (by aacini) - download from: https://www.dropbox.com/s/rfdldmcb6vwi9xc/findrepl.bat
Place findrepl.bat in the same folder as the batch file or on the path.