How can I run a bat file with spaces in the filepath? - kotlin

I want to run a bat file used to compile sass to css from within a Kotlin program, on a Windows machine. I had everything working using Runtime.exec until I switched to a Windows account that had a space in the username. From what I read, I read that using ProcessBuilder would make this easier. It seems that even with ProcessBuilder I still can't get it to work, no matter what I try.
Here is my code so far
val commands = mutableListOf(
"cmd",
"/c",
"C:\\Users\\John Doe\\VCS\\test\\tools\\sass\\windows\\dart-sass\\sass.bat",
"--no-source-map",
"C:\\Users\\John Doe\\VCS\\test\\src\\main\\sass\\global.scss",
"global.css"
)
val processBuilder = ProcessBuilder(commands)
val process = processBuilder.start()
...
The error I get is 'C:\Users\John' is not recognized as an internal or external command, operable program or batch file. It doesn't help if I surround the strings that have spaces with \".

If I remember correctly, all windows files and folders that have a space in the name have a matching short name in the old 8.3 format replacing additional space and other characters with a tilde (~) and a number.
So whatever is returning you the path for the .bat and .sscs files could return the full filename in that format?
Doesn't solve the problem but avoids it instead, I admit.
Also means you won't get busted when someone puts a space in the filename (OK, unlikely, but still something better to deal with from the start).
Consider something along the lines of the top 2 answers on this superuser thread

This is actually a Windows cmd issue. The question here shows that in cmd, in addition to quoting the file paths, you also have to quote the entire part of the command line text after the /c switch.
I don't know if this is the best way to do it in ProcessBuilder, but I was able to get it to work with the following code.
"cmd.exe",
"/c",
"\"\"C:/Users/John Doe/VCS/test/tools/sass/windows/dart-sass/sass.bat\" "
+ "--no-source-map "
+ "\"C:/Users/John Doe/VCS/test/src/main/sass/global.scss\" "
+ "\"global.css\"\""

Related

How do I tell Octave where to find functions without picking up other files?

I've written an octave script, hello.m, which calls subfunc.m, and which takes a single input file, a command line argument, data.txt, which it loads with load(argv(){1}).
If I put all three files in the same directory, and call it like
./hello.m data.txt
then all is well.
But if I've got another data.txt in another directory, and I want to run my script on it, and I call
../helloscript/hello.m data.txt
this fails because hello.m can't find subfunc.m.
If I call
octave --path "../helloscript" ../helloscript/hello.m data.txt
then that seems to work fine.
The problem is that if I don't have a data.txt in the directory, then the script will pick up any data.txt that is lying around in ../helloscript.
This seems a bit fragile. Is there any way to tell octave, preferably in the script itself, to get subfunctions from the same directory as the script, but to get everything else relative to the current directory.
The best robust solution I can think of at the moment is to inline the subfunction in the script, which is a bit nasty.
Is there a good way to do this, or is it just a thorny problem that will cause occasional hard to find problems and can't be avoided?
Is this in fact just a general problem with scripting languages that I've just never noticed before? How does e.g. python deal with it?
It seems like there should be some sort of library-load-path that can be set without altering the data-load-path.
Adding all your subfunctions to your program file is not nasty at all. Why would you think so? It is perfectly normal to have function definitions in your script. The only language I know that does not do this is Matlab but that's just braindead.
The other alternative you have is to check that the input file argument, data.txt exists. Like so:
fpath = argv (){1};
[info, err, msg] = stat (fpath);
if (err)
error ("could not stat `%s' : %s", fpath, msg);
endif
## continue your script knowing the file exists
But really, I would recommend you to use both. Add your subfunctions in your main program, the only reason to have it on separate file is if you plan on sharing with other programs, and always check input arguments.

How to set and get variables when working in cmd

I am working in cmd to send HTTP GET and POST requests with cURL.
There are many times where I am sending requests to the same pages and typing them out every time is a huge pain.
I'm trying to figure out how to use set= so that I can save these URLs for each time I want to use them.
I've tried
C:\>set page = "http://www.mywebpage.com/api/user/friends"
C:\>page
'page' is not recognized as an internal or external command,
operable program or batch file.
C:\>echo %page%
%page%
but it won't return the page name.
How can I accomplish what I need?
C:\Windows\system32>set page="http://www.mywebpage.com/api/user/friends"
C:\Windows\system32>echo %page%
"http://www.mywebpage.com/api/user/friends"
C:\Windows\system32>set page=http://www.mywebpage.com/api/user/friends
C:\Windows\system32>echo %page%
http://www.mywebpage.com/api/user/friends
Don't use spaces around =. Select version with or without " according to your needs. Variable value may contain spaces inside:
C:\Windows\system32>set page=http://www.mywebpage.com/api/user/my friends
C:\Windows\system32>echo %page%
http://www.mywebpage.com/api/user/my friends
You are setting the value "http://www.mywebpage.com/api/user/friends" inside the variable "page " (notice the space) since you have a space before the =.
So you can either retrieve the value by using %page % or by using set page="http://..." without a space between page and the equals sign

ActiveTCL - Unable to run a batch file from an Expect Script

I was originally trying to run an executable (tftpd32.exe) from Expect with the following command, but for some unknown reason it would hanged the entire script:
exec c:/tftpd32.351/tftpd32.exe
So, decided to call a batch file that will start the executable.
I tried to call the batch file with the following command, but get an error message stating windows cannot find the file.
exec c:/tftpd32.351/start_tftp.bat
I also tried the following, but it does not start the executable:
spwan cmd.exe /c c:/tftpd32.351/start_tftp.bat
The batch file contains this and it run ok when I double click on it:
start tftpd32.exe
Any help would be very much appreciated.
Thanks
The right way to run that program from Tcl is to do:
set tftpd "c:/tftpd32.351/tftpd32.exe"
exec {*}[auto_execok start] "" [file nativename $tftpd]
Note that you should always have that extra empty argument when using start (due to the weird way that start works; it has an optional string in quotes that specifies the window title to create, but it tends to misinterpret the first quoted string as that even if that leaves it with no mandatory arguments) and you need to use the native system name of the executable to run, hence the file nativename.
If you've got an older version of Tcl inside your expect program (8.4 or before) you'd do this instead:
set tftpd "c:/tftpd32.351/tftpd32.exe"
eval exec [auto_execok start] [list "" [file nativename $tftpd]]
The list command in that weird eval exec construction adds some necessary quoting that you'd have trouble generating otherwise. Use it exactly as above or you'll get very strange errors. (Or upgrade to something where you don't need nearly as much code gymnastics; the {*} syntax was added for a good reason!)

SDK 2.0 rake file strips \\

I had a script that was running locally, but it failed on Rally.
The reason it turns out is because the script contains the following line:
var regex = new RegExp("/Metrics/" + this.type + "/(\\d+)-(\\d+)");
This is so I can look for a particular string, based on this.type. Unfortunately something in the rake file changes the \\d expressions to \d, which breaks the script. This will probably break any script that relies on a double \ to escape stuff.
I was able to get around this by using [0-9] instead of \d, but it would be nice to get a more robust workaround to this nasty little gotcha.
This issue is fixed as of this commit. You can download the new rake file and rebuild your app.

Inconsistent Behavior In A Batch File's For Statement

I've done very little with batch files but I'm trying to track down a strange bug I've been encountering on a legacy system.
I have a number of .exe files in particular folder. This script is supposed to duplicate them with a different file name.
Code From Batch File
for %%i in (*.exe) do copy \\networkpath\folder\%%i \\networkpath\folder\%%i.backup.exe
(Note: The source and destination folders are THE SAME)
Example Of Desired Behavior:
File1.exe --> Becomes --> File1.exe.backup.exe
File2.exe --> Becomes --> File2.exe.backup.exe
Now first, let me say that this is not the approach I would take. I know there are other (potentially more straight forward) ways to do this. I also know that you might wonder WHY on earth we care about creating a FileX.exe.backup.exe. But this script has been running for years and I'm told the problem only started recently. I'm trying to pinpoint the problem, not rewrite the code (even if it would be trivial).
Example Buggy Output:
File1.exe.backup.exe
File1.exe.backup.exe.backup.exe
File1.exe.backup.exe.backup.exe.backup.exe
File1.exe.backup.exe.backup.exe.backup.exe.backup.exe
File1.exe.backup.exe.backup.exe.backup.exe.backup.exe.backup.exe
File1.exe.backup.exe.backup.exe.backup.exe.backup.exe.backup.exe.backup.exe
etc...
File2.exe.backup.exe
File2.exe.backup.exe.backup.exe
File2.exe.backup.exe.backup.exe.backup.exe
File2.exe.backup.exe.backup.exe.backup.exe.backup.exe
File2.exe.backup.exe.backup.exe.backup.exe.backup.exe.backup.exe
File2.exe.backup.exe.backup.exe.backup.exe.backup.exe.backup.exe.backup.exe
Not knowing anything about batch files, I looked at this and figured that the condition of the for statement was being re-evaluated after each iteration - creating a (near) infinite loop of copying (I can see that, eventually, the copy will fail when the names get too long).
This would explain the behaviour I'm seeing. And when cleaned the directory in question so that it had only the original File1.exe file and ran the script it produced the bug code. The problem is that I CANNOT replicate the behaviour anywhere else!?!
When I create a folder locally with a few .exe files and run the script - I get the expected output. And yes, if I run it again, I get one instance of 'File1.exe.backup.exe.backup.exe' (and each time I run it again, it increases in length by one). But I cannot get it to enter the near-infinite loop case.
It's been driving me crazy.
The bug is occurring on a networked location - so I've tried to recreate it on one - but again, no success. Because it's a shared network location, I wondered if it could have something to do with other people accessing or modifying files in the folder and even introduced delays and wrote a tiny program to perform actions in the same folder - but without any success.
The documentation I can find on the 'for' statement doesn't really help, but all of the tests I've run seem to suggest that the in (*.exe) section is only evaluated once at the beginning of execution.
Does anyone have any suggestions for what might be going on here?
I agree with Andriy M's comment - it looks to be related to Windows 7 Batch Script 'For' Command Error/Bug
The following change should fix the problem:
for /f "eol=: delims=" %%i in ('dir /b *.exe') do copy \\networkpath\folder\%%i \\networkpath\folder\%%i.backup.exe
Any file that starts with a semicolon (highly unlikely, but it can happen) would be skipped with the default EOL of semicolon. To be safe you should set EOL to some character that could never start a file name (or any path). That is why I chose the colon - it cannot appear in a folder or file name, and can only appear after a drive letter. So it should always be safe.
Copy supports wildcard characters also in target path. You can use
copy \\networkpath\folder\*.exe \\networkpath\folder\*.backup.exe