Page 1 of 1

How to mask a blank inside nested quotes?

Posted: 28 May 2018 07:24
by pstein
Assume I have the folowing simplified code:

Code: Select all

set PROG=D:\tools\graphic tools\v7\

for /R . %%F in (.jpg) do (

  for /F usebackq %%L in (`"%PROG%myprog.exe" ...... %%F`) do set %%L

   ....
   )
At first mind the blank inside the path.

When I run this batch script I got the folowing error:

'D:\tools\graphic' is not recognized as an internal or external command,
operable program or batch file.
The filename, directory name, or volume label syntax is incorrect.
Missing operator.

I though I could always enclose a string inside another string with an opposite quotes

Either

' "......" ....'
or
" ' .....' ...."

This seems not to be the case.

How else does that work?

Re: How to mask a blank inside nested quotes?

Posted: 28 May 2018 08:28
by sst
Use this from

Code: Select all

for /F usebackq %%L in (`^""%PROG%myprog.exe" ...... %%F^"`) do set %%L
for /F internally runs cmd /c <FOR /F command>
cmd will preserve quotes only when invoked without /S switch which is the case, and if there are exactly just two quote characters on the command line which is also the case and the command that surrounded in quotes ("%PROG%myprog.exe") refers to valid and existing executable name otherwise it will remove the quotes.
The extra escaped quotes are to prevent cmd from removing quotes around your executable name.
pstein wrote:
28 May 2018 07:24
'D:\tools\graphic' is not recognized as an internal or external command,
operable program or batch file.
Its the the indication that "%PROG%myprog.exe" does not refer to an existing file.

I would also recommend to put %%F in quotes

Re: How to mask a blank inside nested quotes?

Posted: 28 May 2018 08:32
by MarioZac
What are those blanks ........ for? Did you try "*.jpg" in FOR /R ? Did you test Echo your resulting variable values? When asking Qs, its better to explain what you try to accomplish with this code, since your code may contradict your goals, while you merely want to mask blanks in it.

Re: How to mask a blank inside nested quotes?

Posted: 28 May 2018 23:00
by jeb
Hi pstein,

as sst said, it's a problem how FOR/F invokes cmd.exe.
It can be solved with the additional quotes like the sample of sst.

Or you prefix your command with CALL

Code: Select all

for /F usebackq %%L in (`CALL "%PROG%myprog.exe" ...... %%F`) do set %%L

Re: How to mask a blank inside nested quotes?

Posted: 30 May 2018 03:10
by sst
Adding to jeb's solution:

Code: Select all

for /F usebackq %%L in (`@"%PROG%myprog.exe" ...... %%F`) do set %%L
The trick with CALL and at-sign(@) here is to prevent the first character that comes after /c switch to be a double quote(") so cmd will not enter command line quote processing phase.

With any of the following 3 solutions

Code: Select all

for /F usebackq %%L in (`^""%PROG%myprog.exe" ...... %%F^"`) do set %%L
for /F usebackq %%L in (`CALL "%PROG%myprog.exe" ...... %%F`) do set %%L
for /F usebackq %%L in (`@"%PROG%myprog.exe" ...... %%F`) do set %%L
Instead of getting this error:
'D:\tools\graphic' is not recognized as an internal or external command,
operable program or batch file.
You will get this:
'"D:\tools\graphic tools\v7\myprog.exe"' is not recognized as an internal or external command,
operable program or batch file.

Re: How to mask a blank inside nested quotes?

Posted: 30 May 2018 08:52
by pieh-ejdsch
In for /f loop - You only must create a first command token with no space

Code: Select all

for /F usebackq %%L in (`if 1 equ 1 "%PROG%myprog.exe" ...... %%F`) do set %%L
Phil

Re: How to mask a blank inside nested quotes?

Posted: 30 May 2018 10:58
by sst
pieh-ejdsch wrote:
30 May 2018 08:52
In for /f loop - You only must create a first command token with no space

Code: Select all

for /F usebackq %%L in (`if 1 equ 1 "%PROG%myprog.exe" ...... %%F`) do set %%L
Phil
That's OK for demonstrating the concept but it should noted that using it as a general method will lead to failure if Command Extensions are disabled bye default. It is rare and uncommon but still a possibility.
and there is no way to force the FOR's cmd instance to start with Enabled Extensions in this situation.
Using if 1==1 instead, will need the equal signs to be escaped when putted inside FOR's IN clause: if 1^=^=1

Re: How to mask a blank inside nested quotes?

Posted: 30 May 2018 16:11
by penpen
sst wrote:
30 May 2018 10:58
and there is no way to force the FOR's cmd instance to start with Enabled Extensions in this situation.
You can just activate it from within the batch before using the extensions (works although the docu of "setlocal /?" says something different (at least under my german localization): The help text is wrong.):

Code: Select all

@echo off
setlocal enableExtensions disableDelayedExpansion
for /F usebackq %%L in (`if 1 equ 1 "%PROG%myprog.exe" ...... %%F`) do set %%L
penpen

Re: How to mask a blank inside nested quotes?

Posted: 30 May 2018 22:50
by sst
@penpen
by saing
sst wrote:
30 May 2018 10:58
..... if Command Extensions are disabled bye default. It is rare and uncommon but still a possibility.
I mean when Command Extensions are disabled at registry level.
Of course Command Extensions can be enabled from within batch file with setlocal but that would enable Extensions for the instance of cmd that is running the batch file but not for the child cmd that is invoked by FOR /F

Using FOR /F implies that we have already enabled extensions, I got your point about the wrong documentation of setlocal, but that's not my concern, my concern is about <if 1 equ 1> command which must be carried by child cmd.

Maybe because I missed 'child' in my sentence... I should have said:
and there is no way to force the FOR's child cmd instance to start with Enabled Extensions in this situation.

One may argue that we can use

Code: Select all

for /F usebackq %%L in (`cmd /e:on /c if 1 equ 1 "%PROG%myprog.exe" ...... %%F`) do set %%L
This will complicate things unnecessarily and we have now two child CMDs, still the first immediate cmd that is invoked bye FOR /F is running with disabled extensions

This is in contrary to pipes which it is possible to invoke immediate child CMDs with enabled or disabled Extensions at will.

Re: How to mask a blank inside nested quotes?

Posted: 31 May 2018 04:49
by penpen
sst wrote:
30 May 2018 22:50
but not for the child cmd that is invoked by FOR /F
I missed that point... .

penpen

Re: How to mask a blank inside nested quotes?

Posted: 11 Jun 2018 01:48
by pstein
Sorry I have to revert back to this problem.
At first thank you for the suggestions so far.

But I am still fiddling around with the batch script.

Originally I want to use the well known free cmdline tool ImageMagic available from here (scroll down for Win release):
http://www.imagemagick.org/script/download.php

With the help of this tool I want to count the number of pictures in a (big) directory which have dimension above a certain (pixel) size.

Therefore I setup the following batch script (see bottom of this posting). I already adjusted the masked internal command as suggested here)

However when I run this batch script in the top node directory of the picture folder tree I am getting always the error:

'D:\todo\IMG v7\magick" identify -ping -format "INC' is not recognized as an internal or external command,
operable program or batch file.
The filename, directory name, or volume label syntax is incorrect.
Missing operator.

When I execute the ImageMagick command from cmdprompt (=not from batch script) for a single picture like

"D:\todo\IMG v7\magick" identify -ping -format "INC=%[fx:w>=400||h>=200?1:0]" D:\todo\dummy.jpg

then everything works.

So the error must be somehow in the batch script statement.

So do I have to mask the double percentage sign near INC as well?

Writing in batch script
^"INC=%%[fx:w>=400||h>=200?1:0]^"
let the batch script execution collapse immediately without error message

Writing in batch script:
^""INC=%%[fx:w>=400||h>=200?1:0]"^"
yields:
'D:\todo\IMG v7\magick" identify -ping -format ""INC=%[fx:w>=400||h>=200?1:0]"' is not recognized as an internal or external command,
operable program or batch file.
Missing operator.

Code: Select all

set IMG7path=D:\todo\IMG v7\

set TOTAL=0
set COUNT=0

for /R . %%F in (*.jpg) do (

  for /F "usebackq" %%L in (`^"%IMG7path%magick^" identify -ping -format "INC=%%[fx:w>=400||h>=200?1:0]"  %%F`) do set %%L

  set /A TOTAL += 1
  set /A COUNT += !INC!
)
echo TOTAL=%TOTAL%
echo COUNT=%COUNT%

Re: How to mask a blank inside nested quotes?

Posted: 11 Jun 2018 02:26
by sst
@pstein
Your are doing it the wrong way. You should reread my post carefully.
Do not touch or escape the existing quotes, just add extra escaped quotes in the first and last position of FOR command.

This is what you did:

Code: Select all

for /F "usebackq" %%L in (`^"%IMG7path%magick^" identify -ping -format "INC=%%[fx:w>=400||h>=200?1:0]"  %%F`) do set %%L
This is what it should be: (Compare it with above carefully to see the difference)

Code: Select all

for /F "usebackq" %%L in (`^""%IMG7path%magick" identify -ping -format "INC=%%[fx:w>=400||h>=200?1:0]"  %%F^"`) do set %%L
Also as I said before, you should enclose %%F in quotes too. That is:

Code: Select all

for /F "usebackq" %%L in (`^""%IMG7path%magick" identify -ping -format "INC=%%[fx:w>=400||h>=200?1:0]"  "%%~F"^"`) do set %%L

If extra escaped quoting still confuses you, just prefix your executable with CALL as jeb suggested:

Code: Select all

for /F "usebackq" %%L in (`CALL "%IMG7path%magick" identify -ping -format "INC=%%[fx:w>=400||h>=200?1:0]"  "%%~F"`) do set %%L
But without understanding the mechanisms behind those suggestions you will probably get it trouble again with slightly different scenarios