What does %var:~0,4% and %var:.=% mean in batch file? - batch-file

Here is my sample batch file code and I really don't know what it does.
set TEMPRPSW=%RPSW_VERSION%
set RELVER=%TEMPRPSW:~0,4%
set RELVER=%RELVER:.=%
if %RELVER% GEQ 30 goto :eof
Please give me a working sample.

That takes a 4 character long substring of TEMPRPSW, starting from character 0.
Meaning, it takes the first 4 characters of TEMPRPSW and puts them in RELVER.
set TEMPRPSW=abcdef
set RELVER=%TEMPRPSW:~0,4%
echo %RELVER% -> will print abcd
%VAR:str=% removes str
set RELVER=123.456
set RELVER=%RELVER:.=%
echo %RELVER% -> will print 123456 with no .
here is a nice article: https://www.dostips.com/DtTipsStringManipulation.php

Related

What does "!S:~%I%,1!"=="" mean?

I found some sample code but I am unable to get what this if condition means:
set /p sourceDB=Enter Source DB: %=%
set S=%sourceDB%
set I=0
set L=-1
:l ----- Forget about this line
if "!S:~%I%,1!"=="" goto ld
if "!S:~%I%,1!"=="/" set K=%I%
if "!S:~%I%,1!"=="#" set Z=%I%
if "!S:~%I%,1!"==":" set Y=%I%
set /a I+=1
goto l
The short answer is that this is how you get substrings in batch.
When you extract a substring, you use the format %string_name:~index_of_first_character_in_substring,length_of_substring% or, if the value of either index_of_first_character_in_substring or length_of_substring is contained in a separate variable (in your example, the index is its own variable), you can enable delayed expansion and use the format !string_name:~%variable_whose_value_is_the_index_of_first_character_in_substring%,length_of_substring!
In this case, your main string is in a variable called %S%, you are starting at character %I%, and grabbing 1 character.
The line you've told us to ignore is actually pretty important, as it's used to loop through the entire string.
The entire line "!S:~%I%,1!"=="" is used to check if the substring is empty -- that is, the script is finished iterating through the string. There are also conditions for if the substring is /, #, and :; with K, Z, and Y respectively containing the indices of those substrings.

What is the error in this batch code?

SET /p con1=----Do you want to display some text?(y/n):
IF con1==y (echo hi)
But this is not displaying "hi" on the command prompt screen.
Use this code
SET "con1=n"
SET /p "con1=----Do you want to display some text (y/n)? "
SET "con1=%con1:"=%"
IF /I "%con1%"=="y" (echo hi)
You forgot the percent signs to reference the value of variable con1. Therefore your IF compared fixed string con1 with fixed string y which are never equal.
The compare is now not case-sensitive because of parameter /I.
A default value is set in case of user just hits enter on prompt.
And last double quotes are removed from entered value in case of user enters one or more " instead of just y or n as otherwise the batch execution would break on line with IF condition because of a syntax error.

Variables that can contain string and/or number

I have a variable that can contain string and/or number but in some case i have to remove numeric characters. So i am basicly;
if defined ARG2 (
for %%b in (0 1 2 3 4 5 6 7 8 9) do set ARG2=!ARG2:%%b=!
)
It works almost all cases but there is a problem. If ARG2 contain nothing but numeric characters its changing ARG2 value to something like 9= . How can i fix this issue or is there a better way to remove numeric characters from variable?
When inputting 888 your for loop will reach 8 and remove all characters from the string. Therefore you have an empty variable. So when you try to remove 9 it expands to nothing, then for some reason (not entirely sure why) cmd doesn't consider the string manipulation, and just displays it (similarly 666 will output 7= and so on). To fix this you simply need to add a check, to see if ARG2 is empty or not.
if defined ARG2 (
for %%b in (0 1 2 3 4 5 6 7 8 9) do if "!ARG2!"=="" ( goto :break ) else set ARG2=!ARG2:%%b=!
)
:break
This will just goto the :break label if ARG2 expands to nothing.
The answers here - How does the Windows Command Interpreter (CMD.EXE) parse scripts? - should give some better explanation of why.

Wierd Results using script to find length of a string?

I was testing this code submitted by unclemeat in this question(UncleMeat referenced this site) when I tested it by inputting some carots(^) it produced some interesting results.
Len.bat
#echo off
setLocal EnableDelayedExpansion
set s=%1
set length=0
:count
if defined s (
set s=%s:~1%
set /A length += 1
goto count
)
echo %length%
Testing of Len.bat
C:\Users\Public>len ^
More?
More?
0
C:\Users\Public>len ^^
12
C:\Users\Public>len ^^^
More?
More?
12
C:\Users\Public>len ^^^^
1
C:\Users\Public>len ^^^^^
More?
More?
1
C:\Users\Public>len ^^^^^^
13
C:\Users\Public>len ^^^^^^^
More?
More?
13
C:\Users\Public>len ^^^^^^^^
22
C:\Users\Public>
Ignoring the double More? where I simply returned without inputting anything, the pattern is:
0
12
12
1
1
13
13
22
22
13
13
2
2
14
14
23
23
14
14
23
23
14
14
23
23
Every odd occurance prompts me with the double More?, which is why it is doubled, but other wise these results are just wierd. I thought it would have to do something with the following line in the code, but there seems to be no relationship!
Any explanation to this irregular data? Or is this just one of those things about cmd....
It has many reasons why the code completly fails with carets.
First the way you try to call your batch will fail.
A caret escapes the next character and is itself removed from the line.
A single caret at a line end escapes the line end (it's called multiline caret), that's the cause why cmd.exe show you the prompt More?.
This will be true for all odd number of carets.
Sample with seven carets.
length ^^^^^^^
More?
More?
cmd.exe will call the length bat with the following string ^^^<newline>.
The newline will be split from the %1 parameter, so in %1 is only ^^^.
But now you this part fails completly
set s=%1
set length=0
As it expands to
set s=^^^
set length=0
As the last caret is now a multiline caret it will append set length=0 to the line!
So in the variable s is now the content ^set length=0.
This will never work ...
Even in this block the %s:~1% will be a cause of further problems, as it will also can expand to multiline carets when s contains carets (when you use 8 carets length ^^^^^^^^).
if defined s (
set s=%s:~1%
set /A length += 1
goto count
)
For some more explanations about the caret you can read
SO:Long commands split over multiple lines in Vista/DOS batch (.bat) file

Deleting last line of every text file in drive using Batch or VBScript

I need to create either a batch file or vbscript to delete every last line of a text file in a drive. So, a text file
Hello.
Blah blah blah.
Goodbye.
will become
Hello.
Blah blah blah.
TIA.
PS: I'm creating projects to learn batch and vbscript. My ultimate goal is to learn the scripting language. So, I would like to request for explanation alongside the code so that I can understand. Thanks.
Here's a commented solution for you.
Be warned that doing something like this is potentially a dangerous operation to run across an entire drive - VBScript does not handle Unicode files very well, so if you run this against a whole drive, be sure you know what you are changing.
I have set it only to work against a sub-directoy (C:\Somedirectory) in my example you would need to change that to where ever you want to go. Also, whilst I have tested this, I can't guarantee it's not going to misbehave: Consider this - if you ran this multiple times, you would end up with a whole bunch of 0 byte (empty) files eventually!
WARNING: This will permanently delete data that you cannot get back. I would not recommend using this blindly against an entire drive!!
DISCLAIMER: Use at your own risk.
Option Explicit
' Option Explicit forces all variables to be declared good way to sanity check some times.
Const ForWriting = 2
Const ForReading = 1
' Set our Contsants for manipulating files read/writes
' Dimension our variables (in our case, the main loop only has one.. objFSO
Dim objFSO
' Load up the FileSystemObject for our file operations later
Set objFSO = CreateObject("Scripting.FileSystemObject")
' Call our routine to recursively scan folders for txt files.
Call Recurse("C:\SomeFolder\")
Sub Recurse(strFolderPath)
' This routine recursively searches a folder/drive for txt files
Dim objFolder, objFile, objSubFolder
' Load up the Folder path into objFolder
Set objFolder = objFSO.GetFolder(strFolderPath)
On Error Resume Next
' Instruct VBScript to continue if an error occurs.
For Each objFile In objFolder.Files
If Err Then
' If there's an error accessing the file, likely to be access denied for files in use, etc. Let's ignore and continue
Err.clear
Else
If (InStr(objFile.Name, ".") > 0) Then
'If the file's extension is "txt", chomp it! (This calls the Function FileChomp with the path\filename.txt)
If LCase(objFso.GetExtensionName(objFile.name)) = "txt" Then FileChomp (objFile.Path )
End If
End If
Next
For Each objSubFolder In objFolder.SubFolders
Call Recurse(objSubFolder.Path)
Next
End Sub
Function FileChomp (FCName)
' This function chomps the last line of a text file.
Dim strdata, objFile, arrlines, strlines, filesize
' This section gets our text file size.
filesize = 0
Set objFile = objFSO.GetFile(FCName)
FileSize = objFile.Size
Set objFile = Nothing
'This resets our array for lines, incase there's something in there already from last time?
ReDim arrlines(0)
' Open the file for reading
Set objFile = objFSO.OpenTextFile(FCName, ForReading)
' If the filesize we retrieved earlier is greater than 0, go do this
If FileSize > 0 then
strLines = 0
Do While objFile.atendofstream = false
' This loop reads in the file we're going to chomp and stores it line by line into arrLines as an array
ReDim Preserve arrLines(strLines)
arrLines(strlines) = objFile.Readline
strLines = strLines + 1
Loop
' This sets the file as we are going to write back to it (less the last line) - BE WARNED This may not work for unicode text files.
Set objFile = objFSO.OpenTextFile(FCName, ForWriting)
For strLines = 0 to UBound(arrLines) - 1
' This For Loop writes out the file (less the last line)
objFile.WriteLine arrLines(strLines)
Next
End If
objFile.Close
End Function
What have you tried?
Start by looking at these commands.
Commands
for,
for /f,
for /r
Use the /? argument for help.
Batch References
SS64,
DosTips,
Rob van der Woude,
Computer Hope
Technet
Bookmark These!
This script for removing last N line, works for you:
count the total line
set Line = Line - N , remain just processing lines number
#echo OFF
setlocal EnableDelayedExpansion
set LINES=0
for /f "delims==" %%I in (input.txt) do (
set /a LINES=LINES+1
)
echo Total Lines : %LINES%
echo.
:: n = 1 , last 1 line will be ignored
set /a LINES=LINES-1
call:PrintFirstNLine > output.txt
goto EOF
:PrintFirstNLine
set cur=0
for /f "delims==" %%I in (input.txt) do (
echo %%I
::echo !cur! : %%I
set /a cur=cur+1
if "!cur!"=="%LINES%" goto EOF
)
:EOF
exit /b
Here call:PrintFirstNLine > output.txt will give the output in an external file name as output.txt .

Resources