Shiwayari
Shiwayari

Reputation: 345

Passing filepath with or without spaces to cygwin inside a batch script.. " ' \ confusion

After hours and countless amounts of putting "s and 's whereever I could possibly imagine and trying to find a resource on how exactly what I'm trying to do is handled, I'm lost in more confusion than before I started trying.. Unfortunately I'm very unfamiliar with batch scripting in windows.

I'm trying to write a batch script, which takes a windows filepath as argument that can contain spaces or not. That filepath should then be passed to a command inside cygwin, and the output, which is just the filepath modified (still a windows filepath), should then be assigned to a variable in the batch script.

I got it to work fully if the filepath does not have spaces.. but I cannot figure out how to do it with spaces. I see "s magically appearing, \s somtimes disappearing, sometimes not... The farthest I could get was this:

@echo off
set "a=%1"
for /f "delims=" %%i in ('C:\cygwin64\bin\bash --login -c "echo '%a%'"') do set "newpath=%%i"
echo %newpath%
pause

This works only for a filepath without spaces (note the 's around %a%). For a path with spaces, I get a syntax error like

-c: line 0: unexpected EOF while searching for `''
-c: line 1: syntax error: unexpected EOF

(translated since my system is not on english). If I remove the 's around %a%, all the \s in the filepath disappear (as expected from cygwin echo) and spaced filepaths are cut off after the first space. If I replace the 's by "s instead, like this

@echo off
set "a=%1"
for /f "delims=" %%i in ('C:\cygwin64\bin\bash --login -c "echo "%a%""') do set "newpath=%%i"
echo %newpath%
pause

then it works only for paths with spaces, but not for ones without (all \s disappear). At this point I'm very confused what's going on.

Obviously I want to pass literal 'windows\file\path' including single quotes to cygwin, since then everything inside 's is treated literal. According to some online source ' in batch has no special meaning except for in this special for /f as I wrote it. However, even if I remove the for /f and variable assignment, and try to directly echo instead, I also get similar weird behavior, which does not help me understand anything.

Can anyone help, how do I achieve what I'm trying to do (written in italic above)?


Edit

Did some further testing and I think I understand now the behavior, but I still don't know how to achieve what I want.

So, in batch script, if I pass a path without a space, the variable contains

C:\some\path\without\space

but if I pass a path with space, the variable contains

"C:\some\path with space"

i.e. in the second case, the "s are contained in the variable. So if I pass the former to cygwin echo, I get

echo C:\some\path\without\space

which will output

C:somepathwithoutspace

as expected. If I pass the second version

echo "C:\some\path with space"

the output is

C:\some\path with space

again as expected. Likewise, if I add "s around the variable in the batch script, cygwin echo will just have those additional "s also passed, which results in the swapped behavior, the non-space path get output correctly, while the one with spaces fails because "" is just the empty string in bash.

Imho this behavior is extremely.. silly. To achieve what I want I need to somehow determine if the content of the variable is already quoted or not, and add quotes if neccessary.


Probably not important, but to answer a question from the comments, what I want to do is of course not just use echo, but various bash scripts that do something with the path I passed to it. In the end I want a program I can quickly run in windows / will probably add to my context menu, so doing everything in cygwin bash defeats the purpose of making the final program usable in a quick manner or at least I wouldn't know how to. The reason I don't do everything in batch script is that I don't really know batch scripting at all, I'm just using the bare minimum I have to for the purpose of making a quickly accessible program; while doing the essence in bash since I know how to already.

E.g. I have a .zip file, somewhere, which I want to unpack, count files, run some linux commands on the files (like convert), analyze file names, modify file names, and in the end run another windows program on the modified files. The intermediate steps already require some linux tools; plus all the file handling I have no idea how to do in batch but is very easy in bash..

My only issue is this question since I want to run the final program in any directory that an archive I want to use the program on happens to be, i.e. it could or could not have spaces in the filepath.

Upvotes: 1

Views: 464

Answers (1)

Shiwayari
Shiwayari

Reputation: 345

Turns out all I need is to read the passed filepath like this

@echo off
set "path=%~1"
for /f "delims=" %%i in ('C\cygwin64\bin\bash --login -c "./some/script.sh ""%path%"""') do set "outvar=%%i"
:: do more things ..

where I have used

%~1

instead of

%1

to read my filepath argument. This prevents any "s inside the contents of the variable, so I can always add literal quotes when passing it to cygwin by escaping the double quotes using

""

Upvotes: 1

Related Questions