Windows 7 Batch if statement remove last slash - batch-file

I'm trying to check a variable that contains a path to see if there is a trailing slash and if there is then remove it. I have it working if the variable value is not surrounded by quotes but I also need to check for the trailing slash even if quotes exist.
The issue that I'm running into is trying to get an If statement to work to check for the double quote so I can basically check if it has a double quote and then check for the trailing slash. The If statement fails with "( was unexpected at this time". I'm sure it's an escaping issue but I've tried every way I can think of and haven't been able to get it to work. I've been searching on the web for hours with no luck.
Here's what I have for it so far (I left out the code checking for it without the quotes, basically the same format). Also, if there's a better way to achieve this I'm all ears.
set appRoot="C:\test\"
REM grab the last two characters
set lastChar=%appRoot:~-2%
if %lastChar% == \" (
echo It works!
)

This is a robust method
#echo off
set appRoot="C:\test\"
for %%a in (%approot%) do for %%b in ("%%~a\.") do echo "%%~fb"
pause
If you can change the layout of quotes in the set statement then this is simpler:
#echo off
set "appRoot=C:\test\"
for %%a in ("%approot%\.") do echo "%%~fa"
pause

Once the line if %lastChar% == \" ( is expanded (variables replaced with values), what you get is if \" == \" ( which is not a valid condition, so the parenthesis is not expected.
With the value assigned to appRoot, your best option is directly check not the last but the previous character with
set "lastChar=%appRoot:~-2,1%"
if %lastChar% == \
Or, if you can change the value of appRoot
set "appRoot=C:\test\"
REM grab the last character
set lastChar=%appRoot:~-1%
if %lastChar% == \ (
echo It works!
)
EDITED to adjust to comments
Since the OP don't have control on how the paths are asigned to the variables, the possible cases are: variables in the form set var=, set var="path", set var=path or set "var=path" (we can assume the two last are equivalent if no special characters present). With or without trailing backslash. With or without spaces in path. And the need is to get a correct path (good looking, exists or not, this to be checked later), without trailing backslashes and (not in OP question, but should be) with or without quotes in a consistent manner.
So, here we go
#echo off
setlocal enableextensions
set "appRoot=c:\some where\"
call :cleanToFullPath appRoot
echo %appRoot%
set "appRoot=c:\some where"
call :cleanToFullPath appRoot
echo %appRoot%
set appRoot="c:\some where\"
call :cleanToFullPath appRoot
echo %appRoot%
set appRoot="c:\some where\a\"
call :cleanToFullPath appRoot
echo %appRoot%
set appRoot=c:\some where\in a rare place
call :cleanToFullPath appRoot
echo %appRoot%
set appRoot=""
call :cleanToFullPath appRoot
echo %appRoot%
goto :EOF
:cleanToFullPath variableName
rem Prepare environment
setlocal enableextensions enabledelayedexpansion
rem get variable name
set "_varName=%~1"
rem get value of variable
set "_tmp=!%~1!"
rem remove quotes from variable value
set "_tmp=%_tmp:"=%"
rem handle empty variables. Default current folder
if not defined _tmp set "_tmp=."
rem prepare to process trailing bar if any
if "%_tmp:~-1%"=="\" set "_tmp=%_tmp%."
rem resolve to full path
for %%# in ("%_tmp%") do set "_tmp=%%~f#"
rem cleanup and update variable
endlocal & set "%~1=%_tmp%"
goto :eof

Related

Why batch searches files only in .bat file directory?

I'm trying to make a file search engine in batch but it searching only files in the folred where the .bat file is.
This is full code:
#echo off
title Search engine
set path=%HOMEDRIVE%
set filename=\%empty\%
set filextension=\%empty\%
cls
REM echo Under the construction
REM pause
REM call main.bat
:search
cls
echo Where do you want to search? (Leave empty for %HOMEDRIVE%)
set /p path=
:name
cls
echo Whats the name of your file? (Without extension)
set /p filename=
if %filename% == \%empty\% goto :name
:extension
cls
echo What's the extension of your file?
set /p filextension=
if %filextension% == \%empty\% goto :extension
goto :searchingMessage
:searchingMessage
cls
echo Searching %filename%.%filextension% in %path% (This may take a while)
goto :searching
:searching
for /r %path% %%a in (*) do if "%%~nxa"=="%filename%.%filextension%" set p=%%~dpnxa
if defined p (
echo File found under %p%
) else (
echo File not found
)
pause
call main.bat
Thanks. And I'm sorry if it is something simple. Im new to the batch
Use a setlocal line after #echo off. This ensures that variables that have been set within your code in one run are not preserved for the next run within the same cmd instance.
Never change the value of the variable path. It is system-defined and contains a semicolon-separated ordered list of the directories searched for an executable if that executable is not found in the current directory.
Use the syntax set "var=value" for string-assignments. This syntax ensures that any trailing spaces in a set command are not appended to the value assigned to the variable.
to assign a value of nothing (which actually deletes the variable from the environment) use the syntax set "var=". The code you have used would set the variable to \ concatenated with the value of the variable empty\. In batch, % escapes %, not \ and ^ escapes for other characters that require to be escaped USUALLY.
if %var% == something dosomething would be interpreted as if == something dosomething if var is empty, if %var% == dosomething if something is intended to be empty and if == dosomething if both are empty; all generating a syntax error since the second string following the if is not a comparison-operator like ==. To detect empty, use if defined var dosomething, if not defined var dosomething or if defined var (dosomething) else (dosomethingelse) as appropriate - noting that the string ) else (, if used, must all be on the same physical line.
Note that set /p var=whatever, or preferably set /p "var=whatever" will not change var if the response is simply Enter. It is therefore prudent to execute a set "var=" on the line before a set/p. This characteristic can be used to set a default value:
set "var=xyz"
set /p "var=new value for var [%var%] ^> "
which should prompt with new value for var [xyz] > and will retain xyz as the value of var if the response is simply Enter. Note here that the > is a special character (a redirector) so it's escaped by ^.
Note that if p is defined before the for /r ... line and no file is found, then p will not be assigned by the for /r, and will retain its original value. This is especially important in the light of point (1), where p may be retained between runs. BUT - note the possibility to use this characteristic...
set "p=File not found"
for /r ....
echo %p%
... and please use more expressive variable-names.

Extract a GUID from XML in batch script

I have a string
<?define customGUID= "DA7C36F0-A749-4CC5-9575-398C06039325"?>
I am trying to trim out DA7C36F0-A749-4CC5-9575-398C06039325 from this line.
To begin with I tried to set this string in a variable but I am not able to do that may be because of < and ? in string, I tried:
set "var=<?define customGUID= "DA7C36F0-A749-4CC5-9575-398C06039325"?>"
But later I was able to fetch the string somehow at runtime and now I have the variable
line=<?define customGUID= "DA7C36F0-A749-4CC5-9575-398C06039325"?>
I am not able to figure out how can I trim only value i.e DA7C36F0-A749-4CC5-9575-398C06039325 out of this variable using batch script.
I gave it a try to trim suffix at least with:
set "line=%line:"?>%"
But getting error, can anyone help with better approach?
Note: the spaces are included in string
You can split the string using " as a delimiter, but since quotes are used to specify for loop options, the syntax looks a little different than usual:
#echo off
setlocal enabledelayedexpansion
set "line=<?define customGUID= "DA7C36F0-A749-4CC5-9575-398C06039325"?>"
echo !line!
for /f tokens^=2^ delims^=^" %%A in ("!line!") do set "line=%%A"
echo !line!
You may use this very simple trick:
#echo off
setlocal EnableDelayedExpansion
set "var=<?define customGUID= "DA7C36F0-A749-4CC5-9575-398C06039325"?>"
set "i=0" & set "v0=%var:"=" & set /A i+=1 & set "v!i!=%"
echo Desired string: [%v1%]
If you want to know how this works, remove the #echo off line and carefully review what appears in the screen...
Your command line:
set "line=%line:"?>%"
does not make sense, because there is an =-sign missing (refer to sub-string substitution):
set "line=%line:"?>=%"
To trim away the unwanted prefix you could remove everything up to the first quotation mark:
set "line=%line:*"=%"
However, this only works when you do that after having removed the suffix, because you are dealing with unbalanced quotation marks, which are problematic together with immediate variable expansion. If you want to change the order, you have to implement escaping in order not to exhibit the redirection operator > unquoted:
set ^"line=%line:*"=%"
set "line=%line:"?>=%"
To avoid the need of escaping depending on the input string, use delayed variable expansion, like this:
set "line=<?define customGUID= "DA7C36F0-A749-4CC5-9575-398C06039325"?>"
set line
rem // First enable delayed expansion:
setlocal EnableDelayedExpansion
rem // Then apply it by replacing `%` with `!`:
set "line=!line:*"=!"
set "line=!line:"?>=!"
set line
rem // This restores the previous state:
endlocal
rem // At this point changes in the variable are no longer available due to localisation:
set line

How to escape special characters in Windows batch?

How to replace the string 1234567890 by !##$%^&*() in Windows batch file?
set temp_mm=1234567890
echo befor:%temp_mm%
set temp_mm=%temp_mm:1=!%
set temp_mm=%temp_mm:2=#%
set temp_mm=%temp_mm:3=#%
set temp_mm=%temp_mm:4=$%
set temp_mm=%temp_mm:5=^%%
set temp_mm=%temp_mm:6=^^%
set temp_mm=%temp_mm:7=^&%
set temp_mm=%temp_mm:8=^*%
set temp_mm=%temp_mm:9=^(%
set temp_mm=%temp_mm:0=^)%
echo after:%temp_mm%
#ECHO Off
SETLOCAL
set temp_mm=12345678901234567890
echo befor:%temp_mm%
set "temp_mm=%temp_mm:1=!%"
set "temp_mm=%temp_mm:2=#%"
set "temp_mm=%temp_mm:3=#%"
set "temp_mm=%temp_mm:4=$%"
set "temp_mm=%temp_mm:6=^%"
set "temp_mm=%temp_mm:7=&%"
set "temp_mm=%temp_mm:8=*%"
set "temp_mm=%temp_mm:9=(%"
set "temp_mm=%temp_mm:0=)%"
SETLOCAL enabledelayedexpansion
FOR %%a IN (%%) DO set "temp_mm=!temp_mm:5=%%a!"
ENDLOCAL&SET "temp_mm=%temp_mm%"
echo after:"%temp_mm%"
SET temp_
GOTO :EOF
You appear to have non-ANSI characters in your post.
Personally, I'd use sed since actually using the variable thus-converted may be problematic.
The substitute construct targets the nominated string and replaces it with the second string. This is all well and good for most characters, but fails for some specials (like %) because the syntax doesn't distinguish between % being a substitute character (even when escaped by the normal %) and being end-of-replacement-string. The syntax of "temp_mm=%temp_mm:a=%%" and "temp_mm=%temp_mm:a=%%%" is ambiguous - is it replace with "%" or replace with
escaped "%" or replace with *nothing*, then add "%", "escaped-%" or "%%"?
By using the setlocal/endlocal bracket, you can use two-stage replacement, the first stage sets the replacement string to % as that is the content of %%a, but the initial parsing has then been completed, so % is no longer a special character. The second parsing phase occurs using % as the replacement.
Then all you need is to return the modified variable to the original context.

Batch Removing double quotes or escaping properly ampersand

I want to execute some program passing an argument. The argument changes depending of the day of week and it is an url
Code:
#echo off
setlocal enableDelayedExpansion
for /f %%a in ('wmic path win32_localtime get dayofweek /format:list ^| findstr "="') do (set %%a)
if %dayofweek% == 7(
EXIT
)
set link="http://backlog.telecom.pt/maps/selector/download?map_name=workline_fornecedores&organization_id=1"
if %dayofweek%==5 (
set link="http://backlog.telecom.pt/maps/selector/download?map_name=all_fornecedores&organization_id=1"
)
REM start /wait D:\Planview\Services\BackLog_Integration_Client_Service\Backlog_Integration_Client_Exe\Backlog_Integration_Client_Exe.exe %link%
REM timeout /t 600 /nobreak > NUL
REM start D:\Planview\Services\PV_Backlog_ProcessData_Service\PV_Backlof_ProcessData_Exe\PV_Backlog_ProcessData_Exe.exe
I read that ^ before & would work to escape the & char, but for me it never did and the only way i managed to do it was enableDelayedExpansion and encapsulate the url in ", but this brought me a problem.. my variable instead of having the url has "url".
I tried to do set link=%link:"% but it did not worked.
I'll try to give you some advice via simple examples:
#setlocal enableDelayedExpansion
rem This fails because & is a "poison" character (an instruction or operator)
echo abc&xyz
rem This succeeds because & is escaped
echo abc^&xyz
rem This succeeds because & is quoted
echo "abc&xyz"
rem This succeeds, but it consumes the escape: stored value = abc&xyz
set test=abc^&xyz
rem So this fails because & is not escaped
echo %test%
rem You could "fix" above by double escaping when doing SET so stored value = abc^&xyz
rem But I don't like this - I pretty much never do it
set test=abc^^^&xyz
rem Now this works
echo %test%
rem Better to single escape and use delayed expansion.
set test=abc^&xyz
rem This works because poison characters don't bother delayed expansion
echo !test!
rem You could use quotes instead of escape, but now quotes are in value
set test="abc&xyz"
rem Delayed expansion is not needed because value is quoted
echo %test%
rem Putting the leading quote before the variable still quotes everything
rem But now the quotes are not in the value, as desired. Value = abc&xyz
set "test=abc&xyz"
rem Now you must use delayed expansion because value is not quoted
echo !test!
So the general rules of thumb that I like to use when poison characters are involved:
Use quotes around the entire assignment when SETting a variable: set "var=value"
Use delayed expansion when expanding a variable: !var!
Wouldn't it be nice if those rules solved everything. But of course batch is not that simple. There are situations where these simple rules will fail, but it should be enough to get you started.

Problems with removing Trailing \ in batch file

I have a problem removing trailing \ in a script, my current script is:
echo on
setlocal enableextensions enabledelayedexpansion
SET SCRIPTFOLDER=C:\install$
FOR /F "tokens=* delims=," %%a in (%SCRIPTFOLDER%\GetFilesandFoldersFromHere.Txt) DO (
set data.path=%%~pa
SET data.path=%data.path:~0,-1%
echo %data.path%
rem echo file and folder= %%~na%%~xa Folder=%data.path%
)
The GetFilesandFoldersFromHere.Txt file has lines of files and location e.g.:
T:\First File Here\Move this File.txt
When I run the above code I get:
C:\install$\file Archive Scripts>(
set data.path=\First File Here\
rem If ~-1data.path:~0,0
SET data.path=~0,-1
echo
rem echo file and folder= Move this File.txt Folder=
I want to assign data.path the directory (without drive letter and the trailing ). It assigns the value but when I try to get rid of the trailing \ the value is nulled.
Does anyone have an idea whta is wrong with the code? I am sure it is a simple solution. Been banging my head against this screen, can't see the woods from the tree at the moment.
The problem is that when the for code block (the code enclosed in parenthesis) is parsed, all the variable read operations are replaced with the value in the variable before starting to execute, and in each iteration what is used is this initial value, and not the value stored into the variable during the execution.
If you change a variable inside a block of code and need to access the changed value inside the same block of code, you need to enable delayed expansion (setlocal enabledelayedexpansion) and change (where necessary) the syntax to access the variables to use !varName! instead of %varName%. This indicates to the parser that this read operation must be delayed.
So, in your code you have delayed expansion enabled, but
SET data.path=%data.path:~0,-1%
echo %data.path%
should be something like
SET data.path=!data.path:~0,-1!
echo !data.path!
Here's a trick to remove the trailing backslash
#echo off
set "folder=c:\data\"
for %%a in ("%folder%\.") do set "folder=%%~dpnxa"
set fold
pause

Resources