No, single quotes never need to be escaped. Something like
FOR /F %%A IN ('someCommand 'someParameter' additionlParameter') DO ... works just fine.
Also, there should not be any need to CALL a command within the IN() clause, even if it happens to be a batch script.
The primary problem stems from the fact that FOR /F executes the command via CMD /C, and that plays games with double quotes. Below is the relevant documentation from HELP CMD:
partial HELP CMD output wrote:
If /C or /K is specified, then the remainder of the command line after
the switch is processed as a command line, where the following logic is
used to process quote (") characters:
- If all of the following conditions are met, then quote characters
on the command line are preserved:
- no /S switch
- exactly two quote characters
- no special characters between the two quote characters,
where special is one of: &<>()@^|
- there are one or more whitespace characters between the
two quote characters
- the string between the two quote characters is the name
of an executable file.
- Otherwise, old behavior is to see if the first character is
a quote character and if so, strip the leading character and
remove the last quote character on the command line, preserving
any text after the last quote character.
The conditions for option 1 fail because the variables will have been expanded by the time CMD /C sees the text, and there are more than two quote characters. So option 2 is followed, and the quotes are corrupted.
If you don't really need quotes around, !adb!, then the simplest solution is to drop them. But I will assume they are there for a reason.
The solution is to place an extra set of quotes around the entire command that will be stripped by option 2 of CMD /C.
I think in your case you can simply do the following:
Code: Select all
for /F "tokens=1,2 delims= " %%a in ('""!adb!" !android_cmd!"') do ...
For the first round of parsing, the wrong text is quoted: !adb! is unquoted, and " !android_cmd!" is quoted. But there are no special characters, so there is no harm.
But a more generic option is to escape the first and last quote. This way you introduce the quotes needed by CMD /C without disturbing your quoting semantics.
Code: Select all
for /F "tokens=1,2 delims= " %%a in ('^""!adb!" !android_cmd!^"') do ...
There is one additional problem - You cannot escape a double quote once quoting has begun, so the following assignment actually preserves the first caret as a literal.
Code: Select all
set "android_cmd=shell ^"su -c 'cat /proc/!local_app_pid!/status'^""
The assigned value becomes
Code: Select all
shell ^"su -c 'cat /proc/!local_app_pid!/status'"
Because there are no poison characters in the assignment, you can simply drop the escape.
Code: Select all
set "android_cmd=shell "su -c 'cat /proc/!local_app_pid!/status'""
Or you can escape the outer set of quotes (I think this is the most robust form that is generally applicable)
Code: Select all
set ^"android_cmd=shell "su -c 'cat /proc/!local_app_pid!/status'"^"
Or you can drop the outer set of quotes, but then you run the risk of inadvertent trailing spaces being included in the assignment
Code: Select all
set android_cmd=shell "su -c 'cat /proc/!local_app_pid!/status'"
Dave Benham