How do I use a single quote in for /F command - windows

I want to have .bat script to check if an IIS plugin exists, here is what I tried to assign a variable with the output of command,
set appcmd=%WINDIR%\System32\inetsrv\appcmd.exe
set cmd_list=%appcmd% list config -section:isapiFilters /text:[path='D:\iisplugins\F5XForwardedFor.dll'].path
for /f "usebackq" %%s in (`%cmd_list%`) do set filterPath=%%s
echo %filterPath%
But it didn't work, the output from command prompt:
set filterPath=ERROR
echo ERROR
It seems "=" needs to be escaped, so I tried again,
set cmd_list=%appcmd% list config -section:isapiFilters /text:[path^='D:\iisplugins\F5XForwardedFor.dll'].path
It still didn't work, "^" needs also be escaped? Tried one more time,
set cmd_list=%appcmd% list config -section:isapiFilters /text:[path^^='D:\iisplugins\F5XForwardedFor.dll'].path
Still did not work. Even the single quotes were escaped.
If executed the command alone without assigning to a variable, it worked well and returned the correct path of iis filter,
D:\iisplugins\F5XForwardedFor.dll

Found the solution, to add double quotes in the criteria,
set cmd_list=%appcmd% list config -section:isapiFilters /"text:[path='D:\iisplugins\F5XForwardedFor.dll'].path"
for /f "usebackq" %%s in (`%cmd_list%`) do set filterPath=%%s
echo %filterPath%
Instead of assigning the command result to a variable, it also does work for me to check "ERRORLEVEL".
%appcmd% list config -section:isapiFilter /text:[path='D:\iisplugins\F5XForwardedFor.dll'].path | findstr F5XForwardedFor
if %ERRORLEVEL% == 1 ( echo "Found" )
if %ERRORLEVEL% == 0 ( echo "Not Found")

You shouldn't need to make changes to a working command, just enclose it in doublequotes.
For /F "Delims=" %%A In ('"%cmd_list%"') Do Set "filterPath=%%A"
Full Example:
#Echo Off
Set "appcmd=%__APPDIR__%inetsrv\appcmd.exe"
Set "cmd_list="%appcmd%" list config -section:isapiFilters /text:[path='D:\iisplugins\F5XForwardedFor.dll'].path"
Set "filterPath="
For /F "Delims=" %%A In ('"%cmd_list%" 2^>Nul') Do Set "filterPath=%%A"
If Defined filterPath Echo %filterPath%
Pause

Related

Does the current directory exist in %PATH%?

I tried so many possibilities to achieve this but I keep on getting errors.
I dont know why I can't pass %CD% and %PATH% to FINDSTR.
#echo off
findstr %cd% %path%
echo %errorlevel%
pause
The result is findstr can't take value from %path% because it is not a file so I tried to echo it to file.
#echo off
echo %path% > path.txt
findstr %cd% path.txt
echo %errorlevel%
pause
For now findstr could open path.txt but couldn't get the string to compare. The %cd% didn't appear to work so I tried to put it manually like this:
#echo off
echo %path% > path.txt
findstr c:\foo path.txt
echo %errorlevel%
pause
It works!
So how can I get the current directory value and pass the value to findstr? or more plainly, how do I detect if the current directory exists within %PATH% variable.
for %%a in (echo "%path:;=" "%") do if /i "%cd%"=="%%a" echo "found it"
should do this for most situations but there are exceptions.
path may contain relative paths (. or ..) which will not be detected.
path may contain "some;directory" which will not play nicely
and there is no requirement that the drivename appears in path.
So - use with caution.
Run the following small example script which uses FIND and FINDSTR with conditionals and also an IF/ELSE:
#Echo Off
Echo(%PATH%|Find/I "%CD%;">Nul&&(Echo(Found)||Echo(Not Found
Timeout 2
Echo(%PATH%|FindStr/I "%CD%;">Nul&&(Echo(Found)||Echo(Not Found
Timeout 2
SetLocal EnableDelayedExpansion
If /I "!PATH:%CD%;=!"=="!PATH!" (Echo(Not Found) Else Echo(Found
EndLocal
Timeout -1
So that is three different attempts at the same task, how do they work for you?
There is not any universal, simple, direct way to check if the current folder is included in the path variable using findstr because for each referenced folder inside path: it can be an absolute or relative reference, it can include or not an ending backslash, it can be or not quoted, it can include or not special characters, it can include (if quoted) semicolons, ...
In top of that, in order to use findstr to do the check you will need to handle problems with the backslash characters as they are used as escape characters in regular expressions but also in literals when preceding a non alphanumeric character. Try
echo x:\_uno\ | findstr /L /c:"x:\_uno" && echo Yes || echo No
So, you will need to process each value inside the path variable dealing with quoted semicolons, special characters, backslashes, ...
Fortunately this was solved by Jeb and dbenham in the 'Pretty print' windows %PATH% variable - how to split on ';' in CMD shell. Using their code to enumerate the elements it the path variable, and the approach in the Magoo's answer in this question, we can write somenthing like
#echo off
setlocal enableextensions disabledelayedexpansion
rem Flag variable. Assume current folder is not present in path variable
set "present="
rem This code uses:
rem Q: Pretty print %path% https://stackoverflow.com/q/5471556
rem A: Jeb answer https://stackoverflow.com/a/5472168
rem A: dbenham enhancement https://stackoverflow.com/a/7940444
set "var=%path:"=""%"
set "var=%var:^=^^%"
set "var=%var:&=^&%"
set "var=%var:|=^|%"
set "var=%var:<=^<%"
set "var=%var:>=^>%"
set "var=%var:;=^;^;%"
set var=%var:""="%
set "var=%var:"=""Q%"
set "var=%var:;;="S"S%"
set "var=%var:^;^;=;%"
set "var=%var:""="%"
setlocal EnableDelayedExpansion
set "var=!var:"Q=!"
rem Get a reference to current folder (%%c) and check against each
rem delimited value inside the processed variable
for %%c in (.) do for %%a in ("!var:"S"S=";"!") do (
if "!!"=="" endlocal
if %%a neq "" for %%b in ("%%~fa.") do (
if /i "%%~fb"=="%%~fc" set "present=1"
)
)
if defined present (
echo Current folder is INCLUDED in path variable
) else (
echo Current folder is NOT included in path variable
)
For each element in the path, resolve it to the full qualified path and check against the full qualified path of the current folder.

String replacement within FOR /F into batch file

There are a handful of questions on SO that look similar, but I cannot figure out some behaviour and I am looking for help.
Below is a snippet from a batch file I am trying to write which will load in a set of directories and potentially replace letter substitutions with an expanded path, e.g. the properties file might look like:
location1=C:\Test
location2=[m]\Test
Where location1 points to C:\Test and location2 points to C:\Program Files(x86)\MODULE\Test, because [m] is a shorthand to C:\Program Files(x86)\MODULE.
The batch script, to this point, is simply trying to read in the list of file paths and expand/replace the [m].
SET build.dir=%~dp0%
SET progfiles=%PROGRAMFILES(X86)%
IF "%progfiles%"=="" SET progfiles=%ProgramFiles%
SET local.properties=%build.dir%local.properties
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /F "tokens=1* delims==" %%i IN (%local.properties%) DO (
SET local.dir=%%j
SET local.dir=!local.dir:[m]=%progfiles%\MODULE!
echo !local.dir!
)
ENDLOCAL
Running this kicks out an error:
\MODULE was unexpected at this time.
If I replace the FOR with the following instead:
set test="[m]\Proj\Dir"
set test=!test:[m]=%progfiles%\MODULE!
echo %test%
I get the desired C:\Program Files(x86)\MODULE\Proj\Dir printed out...so I'm confused why it works fine outside of the FOR loop.
My understanding about delayed expansion is that it 'expands' at runtime...which you get to happen using !! instead of %% wrapped around the variable. Furthermore, as I'm creating the local.dir variable inside the FOR loop scope, I must use delayed expansion in order to access it with the updated value for the iteration.
I feel like the problem is using %progfiles%, like there's some special syntax I need to use in order to make it work but nothing is adding up for me. When I echo %progfiles%, it prints out as C:\Program Files(x86 -- note the missing trailing ).
Any ideas? Thanks
Tested suggestion:
D:\Projects\Test\Build>test
*** "D:\Projects\Test\Build\local.properties"
*** "","C:\Program Files (x86)"
[m]=C:\Program Files (x86)\MODULE
Adding quotes around the whole expression makes it work -- can't use other characters for some reason (like []) -- and since I want to append to the path later, we can safely remove the quotes afterwards:
SET local.dir="!local.dir:[m]=%progfiles%\MODULE!"
SET local.dir=!local.dir:"=!
Test this to see if you can nut out the issue:
The double quotes are to provide robust handling in a system with long file/path names.
The () are unquoted which are a problem in a batch script, when inside a loop.
#echo off
SET "build.dir=%~dp0%"
SET "progfiles=%PROGRAMFILES(X86)%"
IF "%progfiles%"=="" "SET progfiles=%ProgramFiles%"
SET "local.properties=%build.dir%local.properties"
echo *** "%local.properties%"
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /F "usebackq tokens=1* delims==" %%i IN ("%local.properties%") DO (
SET "local.dir=%%j"
echo *** "!local.dir!","%progfiles%"
SET "local.dir=!local.dir:[m]=%progfiles%\MODULE!"
echo !local.dir!
)
ENDLOCAL
pause
It has to do with the () characters that end up in your progfiles string. If you take them out, the substitution seems to work fine.
My suggestion is to ditch command for this particular purpose and use one of the other standard tools that Windows comes with. While my personal preference would be Powershell (since it's so much more powerful and expressive), you may just need something quick that you can integrate into existing cmd.exe stuff.
In that case, try the following VBScript file, xlat.vbs:
set arg = wscript.arguments
wscript.echo Replace(arg(0),arg(1),arg(2))
Your batch file then becomes something like, noting the inner for /f which captures the output of the VBS script and assigns it to the variable:
#echo off
SET build.dir=%~dp0%
set progfiles=%PROGRAMFILES(X86)%
if "%progfiles%"=="" set progfiles=%ProgramFiles%
set local.properties=%build.dir%local.properties
setlocal enabledelayedexpansion
for /f "tokens=1* delims==" %%i in (%local.properties%) do (
set local.dir=%%j
for /f "delims=" %%x in ('cscript.exe //nologo xlat.vbs "!local.dir!" "[m]" "%progfiles%\MODULE"') do set local.dir=%%x
echo !local.dir!
)
endlocal
Running that, I get the output:
C:\Test
C:\Program Files (x86)\MODULE\Test
which I think is what you were after.

Redirecting appcmd output to a variable

I am trying to run the following:
FOR /F "tokens=* delims=" %A IN ('C:\windows\system32\inetsrv\appcmd.exe list app /site.name:"car" /xml | C:\windows\system32\inetsrv\appcmd.exe list vdir /vdir.name:"car/" /text:physicalPath') DO SET Variable=%A
But get the following error:
| was unxepected at this time
If the data must be piped from a process to the other, you need to escape the pipe character. It should be ^|
If what you need to do is execute both commands, replace the pipe character with ^&, the command concatenation operator, also escaped
For anyone reaches this, following is working example of batch file to get physical path of iis site , stored in a variable named 'physicalPath'.
This is based on #StuHarper explanations in comments.
#echo off
set site=stackoverflow.com
set site=%site:https://=%
set site=%site:http://=%
set site=%site: =%
set appcmd=%systemroot%\system32\inetsrv\AppCmd.exe
set xmlOutput=%appcmd% list app /site.name:%site% /path:"/" /xml
for /f "tokens=*" %%A in ('%xmlOutput% ^| %appcmd% list vdir /in /text:physicalPath') DO SET physcalPath=%%A
echo physcalPath: %physcalPath%
#echo on

File name with vbs scripts

I want to add a charecter file name.
For Example
123456.jpg --> 1234506.jpg
ABCDEF.jpg --> ABCDE0F.jpg
orginal file 6 charecters new file name 7 charecter (I want to add 0 for all file name Please attention after 0 character has a character.)
for this proccessbatch file or vbs
Regards,
#echo off
setlocal enableextensions disabledelayedexpansion
for /f "delims=" %%a in (
'dir /b /a-d ^|
findstr /r /b
/c:"[^.][^.][^.][^.][^.][^.]\."
/c:"[^.][^.][^.][^.][^.][^.]$"
'
) do (
set "fileName=%%a"
setlocal enabledelayedexpansion
for %%b in ("!filename:~0,5!0!filename:~5!") do endlocal & if not exist "%%~b" echo ren "%%a" "%%~b"
)
This uses dir command to retrieve the list of files and findstr to filter and only get the files with 6 characters in filename. For each file found, the file name is retrieved into a variable, and substring operation is done to compose the new name.
To avoid problems with exclamations in file names, we need to have delayed expansion enabled to read the variable, but disabled to execute the command. This is the reason for the second for, enable delayed expansion, read the required value and store it inside the for command replaceable parameter, disable delayed expansion and now, without problem with exclamations, execute the required command.
The ren command is only echoed to console. If the output is correct, remove the echo to execute the rename operation
Here's how it can be done with VBScript and a FileSystemObject. This script will need to be in the same folder as your files. Otherwise, you'll have to use the full path to your files.
' Files to update...
a = Array("123456.jpg", "ABCDEF.jpg")
With CreateObject("Scripting.FileSystemObject")
For i = 0 To UBound(a)
' Change name. Use first 5 chars, plus "0", plus rest...
.GetFile(a(i)).Name = Left(a(i), 5) & "0" & Mid(a(i), 6)
Next
End With

Windows batch file - splitting a string to set variables

I feel like I'm going around in circles with FOR loop options.
I'm trying to take a string (output of a command) and split it on commas, then use each value to SET, e.g.
String: USER=Andy,IP=1.2.3.4,HOSTNAME=foobar,PORT=1234
So I want to split on comma and then literally use that variable in SET. I don't know ahead of time how many many variables there will be.
I've tried things like:
FOR %%L IN (%MYSTRING%) DO ECHO %%L
but that splits on the equals sign too so I end up with
USER
Andy
IP
1.2.3.4
etc
I just want to be able to do the following so I can SET USER=Andy etc, something like:
FOR %%L IN (%MYSTRING%) DO SET %%L
What option or flags am I missing?
The default delimiters for elements in plain FOR command (no /F option) are spaces, tab, commas, semicolons and equal signs, and there is no way to modify that, so you may use FOR /F command to solve this problem this way:
#echo off
set MYSTRING=USER=Andy,IP=1.2.3.4,HOSTNAME=foobar,PORT=1234
:nextVar
for /F "tokens=1* delims=," %%a in ("%MYSTRING%") do (
set %%a
set MYSTRING=%%b
)
if defined MYSTRING goto nextVar
echo USER=%USER%, IP=%IP%, HOSTNAME=%HOSTNAME%, PORT=%PORT%
Another way to solve this problem is first taking the variable name and then executing the assignment for each pair of values in a regular FOR command:
setlocal EnableDelayedExpansion
set MYSTRING=USER=Andy,IP=1.2.3.4,HOSTNAME=foobar,PORT=1234
set varName=
for %%a in (%MYSTRING%) do (
if not defined varName (
set varName=%%a
) else (
set !varName!=%%a
set varName=
)
)
echo USER=%USER%, IP=%IP%, HOSTNAME=%HOSTNAME%, PORT=%PORT%
EDIT 2023/01/20: New method added
I know this is a very old question. However, I can't resist the temptation to post a new very interesting method to solve this old problem:
#echo off
set MYSTRING=USER=Andy,IP=1.2.3.4,HOSTNAME=foobar,PORT=1234
set "%MYSTRING:,=" & set "%"
echo USER=%USER%, IP=%IP%, HOSTNAME=%HOSTNAME%, PORT=%PORT%
If you want to know where the magic is, remove the #echo off line, execute the program and carefully review the screen...
In case your input is something like HOSTNAME:PORT and you need to split into separate variables then you can use this
#echo off
set SERVER_HOST_PORT=10.0.2.15:8080
set SERVER_HOST_PORT=%SERVER_HOST_PORT::=,%
for /F "tokens=1* delims=," %%a in ("%SERVER_HOST_PORT%") do (
set SERVER_HOST=%%a
set SERVER_PORT=%%b
)
echo SERVER_HOST=%SERVER_HOST%
echo SERVER_PORT=%SERVER_PORT%

Resources