Command parameters truncated when containing '&' charact
Moderators: Hacker, petermad, Stefan2, white
Command parameters truncated when containing '&' charact
When I create a button with an associated command, I found impossible to give this command a parameter containing the character <&> while not containing spaces. This character causes the truncation of the parameter string.
OS : Windows XP SP3 and Windows 7 Pro SP1
Example with a button that creates in the target panel a directory with the same name as the selected directory or file in the source panel :
Command :
dupdir.bat
Parameters :
%T%N
Content of dupdir.bat :
@md %1
It still does not work if I quote the parameters ("%T%N") or add quotes in dupdir.bat.
I think the problem is due to total Commander quoting the parameters string only if this string contains at least one space.
Maybe always quoting the string or never quoting it and letting the user adding the quotes in the parameter string would solve the problem.
OS : Windows XP SP3 and Windows 7 Pro SP1
Example with a button that creates in the target panel a directory with the same name as the selected directory or file in the source panel :
Command :
dupdir.bat
Parameters :
%T%N
Content of dupdir.bat :
@md %1
It still does not work if I quote the parameters ("%T%N") or add quotes in dupdir.bat.
I think the problem is due to total Commander quoting the parameters string only if this string contains at least one space.
Maybe always quoting the string or never quoting it and letting the user adding the quotes in the parameter string would solve the problem.
- ghisler(Author)
- Site Admin
- Posts: 50541
- Joined: 2003-02-04, 09:46 UTC
- Location: Switzerland
- Contact:
Do you mean that the file name contained the "&" character? Or the path?
Maybe it helps to change the dupdir.bat to:
@md "%1"
Maybe it helps to change the dupdir.bat to:
@md "%1"
Author of Total Commander
https://www.ghisler.com
https://www.ghisler.com
It does not work, whether the & is in the path or in the file name.
The string %T%N is truncated before the character &.
This is a problem related with quoting. Without quoting the & has a special meaning in the windows/dos command line.
As I said quoting inside dupdir.bat does not work either.
The parameter string should be quoted before starting <command> <parameter>.
According to my tests, I really think Total Commander only quotes this string when it contains at least one space.
If you try a string with both & and a space, it works.
The string %T%N is truncated before the character &.
This is a problem related with quoting. Without quoting the & has a special meaning in the windows/dos command line.
As I said quoting inside dupdir.bat does not work either.
The parameter string should be quoted before starting <command> <parameter>.
According to my tests, I really think Total Commander only quotes this string when it contains at least one space.
If you try a string with both & and a space, it works.
It is not a TC bug, it is a proper quoting issue for particular external program.
When you start a batch, it is launched via cmd.exe which treats unquoted & as a command separator. So generic rule is to quote every path that is passed to cmd.exe (and batch files too).
"%1" won't help in a batch: it will break quoted parameter, and it will quote only part of unquoted one.
Well, %P%N and %T%N quote parameters if they contain spaces (i.e. time to time) so it is impossible to create 100% working button with these parameters (w/o quotes it will not work with paths containing & and no spaces, with quotes it will not work with paths containing both & and spaces - there were topics asking for explicit quoting for parameters like %P%N). However you can use something like "%T%O.%E" - in this case TC won't add quotes at all so explicit quoting will work.
When you start a batch, it is launched via cmd.exe which treats unquoted & as a command separator. So generic rule is to quote every path that is passed to cmd.exe (and batch files too).
"%1" won't help in a batch: it will break quoted parameter, and it will quote only part of unquoted one.
Well, %P%N and %T%N quote parameters if they contain spaces (i.e. time to time) so it is impossible to create 100% working button with these parameters (w/o quotes it will not work with paths containing & and no spaces, with quotes it will not work with paths containing both & and spaces - there were topics asking for explicit quoting for parameters like %P%N). However you can use something like "%T%O.%E" - in this case TC won't add quotes at all so explicit quoting will work.
Code: Select all
md "%~1"
Regards
Dalai
#101164 Personal licence
Ryzen 5 2600, 16 GiB RAM, ASUS Prime X370-A, Win7 x64
Plugins: Services2, Startups, CertificateInfo, SignatureInfo, LineBreakInfo - Download-Mirror
Ryzen 5 2600, 16 GiB RAM, ASUS Prime X370-A, Win7 x64
Plugins: Services2, Startups, CertificateInfo, SignatureInfo, LineBreakInfo - Download-Mirror
Thank you for your quick answers and tricks.
md "%~1" in the .bat file does not seem to work, because the parameter string must be quoted when Total Commander calls the command, and not afterwards in the .bat file.
But "%T%O.%E" in the parameter field is the solution. With these parameters Total Commander never quotes the parameter string whether or not there are spaces in the string, and the quotes are manually added in the field.
-> Solved
md "%~1" in the .bat file does not seem to work, because the parameter string must be quoted when Total Commander calls the command, and not afterwards in the .bat file.
But "%T%O.%E" in the parameter field is the solution. With these parameters Total Commander never quotes the parameter string whether or not there are spaces in the string, and the quotes are manually added in the field.
-> Solved
- ghisler(Author)
- Site Admin
- Posts: 50541
- Joined: 2003-02-04, 09:46 UTC
- Location: Switzerland
- Contact:
OK, I will quote %P%N if it contains & characters. Are there any other special characters other than & and space I need to put in quotes?
Author of Total Commander
https://www.ghisler.com
https://www.ghisler.com
I guess, you would have to quote if there are characters that have a special meaning in CMD and are allowed in file names at the same time. This applies to &, but also to brackets () and I'm not sure if there's more of them.
Regards
Dalai
Regards
Dalai
#101164 Personal licence
Ryzen 5 2600, 16 GiB RAM, ASUS Prime X370-A, Win7 x64
Plugins: Services2, Startups, CertificateInfo, SignatureInfo, LineBreakInfo - Download-Mirror
Ryzen 5 2600, 16 GiB RAM, ASUS Prime X370-A, Win7 x64
Plugins: Services2, Startups, CertificateInfo, SignatureInfo, LineBreakInfo - Download-Mirror
ghisler(Author),
Try cmd.exe /?, it lists special characters. E.g. in Russian:
Try cmd.exe /?, it lists special characters. E.g. in Russian:
There are many ones so it would be faster to define a bit map to check all of them at once.Специальные символы, которые требуют обязательного заключения в кавычки:
<пробел>
&()[]{}^=;!'+,`~
Code: Select all
static const unsigned char cmdSpecialMap[16] = {
0x00, 0x00, 0x00, 0x00, 0xC2, 0x1B, 0x00, 0x28, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00, 0x68
};
// memset(cmdSpecialMap, 0, sizeof(cmdSpecialMap));
// for (const char* p = "&()[]{}^=;!'+,`~"; *p; ++p) cmdSpecialMap[*p >> 3] |= 1 << (*p & 0x7);
bool isCmdSpecial(wchar_t c) {
if (c > 127) return 0;
return (cmdSpecialMap[c >> 3] & (1 << (c & 0x07))) != 0;
}
const wchar_t* path = "c:\\you & me";
for (const wchar_t* p = path; *p; ++p) {
if (isCmdSpecial(*p)) return true;
}
2MVV, just for my understanding:
Was there REALLY a reason to show Christian how to use char checks in code?
And concerning your code:
Is there REALLY a special reason to entirely use bit masks?
A simple static 128-sized bool/char lookup table is what people normally use, because you'd spare all future bit operations.
Was there REALLY a reason to show Christian how to use char checks in code?
And concerning your code:
Is there REALLY a special reason to entirely use bit masks?
A simple static 128-sized bool/char lookup table is what people normally use, because you'd spare all future bit operations.
TC plugins: PCREsearch and RegXtract
How do you know what people normally use if you can't ask all people?
Bit masks take much less memory and allow the same thing so personally I would use them everywhere when it is possible.
BTW standard C++ STL vector<bool> realization uses bit arrays instead of byte arrays just because there is no any need to use a byte per boolean value.
Bit masks take much less memory and allow the same thing so personally I would use them everywhere when it is possible.
BTW standard C++ STL vector<bool> realization uses bit arrays instead of byte arrays just because there is no any need to use a byte per boolean value.
Well, for one thing because I have experience in programming in teams,MVV wrote:How do you know what people normally use if you can't ask all people?
and because you can read it in every book and online forums: for more than just a handful of results it's a common practice to use LUTs.
I'm talking about sth. like this:MVV wrote:BTW standard C++ STL vector<bool> realization uses bit arrays instead of byte arrays just because there is no any need to use a byte per boolean value.
Code: Select all
In main module/header, etc. :
static const struct _special_lut {
bool lut[128];
_special_lut() {
const char* lut_chars = "&()[]{}^=;!'+,`~";
for(size_t i = 0; i < (sizeof(lut) / sizeof(bool)); i++) {
const char* p = lut_chars;
while(*p && *p != static_cast<char>(i))
p++;
lut[i] = *p ? true : false;
}
}
bool check(const wchar_t* path) const {
for(const wchar_t* p = path; *p; p++) {
if(*p < (sizeof(lut) / sizeof(bool))) {
if(lut[static_cast<size_t>(*p)])
return true;
}
}
return false;
}
} special_lut;
Call:
const wchar_t* path1 = L"c:\\you & me";
if(... special_lut.check(path1))
...
TC plugins: PCREsearch and RegXtract