1

In test.cmd -

wsl echo "Incoming File - $(printf %%q "$(wslpath -ua "%~dpnx1")")"
wsl ls -la "$(printf %%q "$(wslpath -ua "%~dpnx1")")"
pause

In C:\test, I have two files nospace.txt and has space.txt

When I drag nospace.txt to test.cmd -

C:\test>wsl echo "Incoming File - $(printf %q "$(wslpath -ua "C:\test\nospace.txt")")"
Incoming File - /mnt/c/test/nospace.txt

C:\test>wsl ls -la "$(printf %q "$(wslpath -ua "C:\test\nospace.txt")")"
-rwxrwxrwx 1 yvon yvon 0 Feb  2 18:09 /mnt/c/test/nospace.txt

C:\test>pause
Press any key to continue . . .

When I drag has space.txt to test.cmd -

C:\test>wsl echo "Incoming File - $(printf %q "$(wslpath -ua "C:\test\has space.txt")")"
Incoming File - /mnt/c/test/has\ space.txt

C:\test>wsl ls -la "$(printf %q "$(wslpath -ua "C:\test\has space.txt")")"
ls: cannot access '/mnt/c/test/has\ space.txt': No such file or directory

C:\test>pause
Press any key to continue . . .

It seems WSL does not appreciate escapes for white spaces. Why?

4
  • printf %q is only relevant if wsl starts a shell, for which escaping prepares the content. If it merely passes through a literal argument vector, there's no shell unless any code explicitly starts one, thus nothing to read and reverse that escaping. (Even then, printf %q is only safe when there not only is a shell, but when that shell is guaranteed to be the same shell; bash's printf %q can, with some inputs, generate outputs that cannot be correctly parsed by a baseline-standard /bin/sh). Commented Feb 3, 2020 at 3:03
  • @CharlesDuffy Thanks a lot. Is there any comprehensive documentation about escapes in WSL? I tried but did not find any that explains and clarifies what you have said. Commented Feb 4, 2020 at 15:43
  • I don't have any expertise about how WSL is implemented, and was speaking only from knowledge of what the UNIX side looks like, which gives us only a few options about how it could be implemented. Your question and its answer do a lot to narrow down which of those options are actually the case. Commented Feb 4, 2020 at 16:22
  • 1
    ...that said, the Windows side looks very different -- on Windows, the int main(int argc, char**argv) entrypoint isn't the real one but is instead a shim provided by the standard C library, such that a program can replace it with its own; the real entrypoint gets an unparsed command line and can parse it however it chooses. Thus, wsl could be implemented to bypass the default Windows parser and pass the literal text of the command line straight to a UNIX shell if it so chose. (Whereas on UNIX, that's the real interface; programs only see a list of already-parsed C strings). Commented Feb 4, 2020 at 16:25

2 Answers 2

1

Don't use printf. Don't escape the file name at all.

wsl echo "Incoming File - $(wslpath -ua "%~dpnx1")"
wsl ls -la "$(wslpath -ua "%~dpnx1")"

Output -

C:\test>wsl echo "Incoming File - $(wslpath -ua "C:\test\has space.txt")"
Incoming File - /mnt/c/test/has space.txt

C:\test>wsl ls -la "$(wslpath -ua "C:\test\has space.txt")"
-rwxrwxrwx 1 yvon yvon 0 Feb  2 18:09 '/mnt/c/test/has space.txt'
Sign up to request clarification or add additional context in comments.

2 Comments

This smells like a common place where people get tripped up -- thinking that they need to make echo ...some command... output line up with the command they would run without the echo. Because echo runs only after string-splitting, quote removal, glob expansion, &c., making echo emit the "right" thing would require making your quotes literal rather than syntactic -- which is the wrong thing for a correctly functioning command!
@CharlesDuffy This makes the most sense to me.
0

By all means you can use printf with %q to see the escaped version of your input file argument:

wsl printf '%%s' "Incoming File - $(printf '%%q' "$(wslpath -ua "%~f1")")"

However, unless you're copying and pasting it somewhere, I'm not sure why you'd need to do that, so the following should be sufficient:

wsl printf '%%s' "Incoming File - $(wslpath -ua "%~f1")"

Your second command, shouldn't have any issues with the space characters, so there's no need to use printf or %q, the following should suffice:

wsl ls -la "$(wslpath -ua "%~f1")"



If neither of these example lines are your intention, you should consider revising your question, to make it clear what you intended to ask.

1 Comment

printf's first argument should always be a format string. If you want it to print data literally, without modification, but follow it with a newline, make that format string %s\n, as in printf '%s\n' "$data", instead of printf "$data". When you substitute data into the format-string position without knowing whether that data will contain literal backslashes or % characters, results are unpredictable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.