Open Cygwin on a path passed as the first parameter to bash.exe - batch-file

I'm going mad trying to achieve this. I read a lot of questions over Stack Overflow, but they didn't work. I'm trying to open a tab on console2 that opens Cygwin on the path passed as a parameter to it.
For cmd.exe, is quite easy:
cmd.exe %1
For Cygwin, this looks really hard:
bash --login -i -c 'cd `cygpath \'D:\Program Files\'`;exec bash'
The problem here is that with path without spaces it works well, with spaces, it doesn't work. Also, I don't know how to pass a param to it, maybe $1 or %1?
Edit 1:
I'm almost there, I created this batch file that should be run instead of bash.exe directly:
#echo off
set CHERE_INVOKES=%CD%
set TORUN="D:\Program Files\Cygwin\bin\bash.exe" --login -i -c 'cd "%CHERE_INVOKES%"; exec bash'
echo %TORUN%
call %TORUN%
PAUSE
This works with all paths except C: (and D:), the reason? Windows is stupid, and instead of having a path called C:, it has a path called C:!!! So, while all paths ends without a backslash, the first path ends with it, driving me mad!

The following command works for me:
c:\cygwin\bin\bash --login -i -c "cd '%~1'; exec /bin/bash.exe"
Where %~1 expands %1 removing any surrounding quotes (") — see help for in command prompt.
See also: chere package in Cygwin, and ConEmu terminal :)

Here is the solution:
#echo off
set CHERE_INVOKES=%CD%
::Remove trailing slash if required
IF %CHERE_INVOKES:~-1%==\ SET CHERE_INVOKES=%CHERE_INVOKES:~0,-1%
set TORUN="D:\Program Files\Cygwin\bin\bash.exe" --login -i -c 'cd "%CHERE_INVOKES%"; exec bash'
call %TORUN%
I added this code from this question: Remove Trailing Slash From Batch File Input
::Remove trailing slash if required
IF %CHERE_INVOKES:~-1%==\ SET CHERE_INVOKES=%CHERE_INVOKES:~0,-1%
In this way I can use this batch file to open Console2 Cygwin on the current path.

Related

How to redirect output of CMake into a File instead of windows cmd prompt

I am calculating the compiling time for a C project using CMake for compilation statistics.
Below you can see the CMake cmd's which I am using for printing the compilation time:
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CMAKE_COMMAND} -E time")
set_property(TARGET ${MAIN_TARGET} PROPERTY RULE_LAUNCH_COMPILE "${CMAKE_COMMAND} -E time")
This lines of code printing out in windows cmd prompt (e.g.):
Elapsed time: 0 s. (time), 0.000672 s. (clock)
So the calculation works as expected for me. But I would like to have the calculated time listed in a .txt file instead of printing it out in cmd prompt.
I found a solution here:
How to save CMake output to file?
cmake ... >> output_file.txt 2>&1
cmake ... 2>> output_file.txt
But I didn't understand how to use it for my CMake cmd's which is listed above.
I have tried it as below, but unfortunately it is not working:
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CMAKE_COMMAND} -E time" >> output_file.txt 2>&1)
set_property(TARGET ${MAIN_TARGET} PROPERTY RULE_LAUNCH_COMPILE "${CMAKE_COMMAND} -E time" >> output_file.txt 2>&1)
What I am doing wrong?
Since RULE_LAUNCH_COMPILE specifies a command prefix, and stream redirection goes at the end of a shell command, using it like this cannot work.
Also, commands as specified in CMake are not shell commands. This means that special characters will not be interpreted, and will just be arguments for the command.
To summerize, what you're trying to do will be expanded into something like:
cmake -E time >> output_file.txt 2>&1 gcc...
This will not be executed by a shell, but by CMake itself, so it is going to fail as time will try to execute a command named ">>".
The solution for you is to use an intermediate script, for example:
#echo off
time %* >> output_file.txt
Let's name this trace.cmd.
The use of %* means that we take all arguments to the script and pass them as arguments to the time command.
Then you can use it like this:
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CMAKE_COMMAND} -E trace.cmd")
Disclaimer: I haven't tested the solution.

Batch macro not working

I'm trying to create a batch program (here called pldl) to make downloading a playlist of songs with youtube-dl easier, the program is
youtube-dl -o "%(playlist_index)s. %(title)s.%(ext)s" -x --audio-format "mp3" %1
which is supposed to just take the first argument (%1) and add it to this long command, so running command_name "playlist_url" would download it in the location I ran it. Unfortunately, it throws an error instead (echo is on for debugging)
E:\Path\To\Music>pldl "https://www.youtube.com/playlist?list=PLSdoVPM5WnndV_AXWGXpzUsIw6fN1RQVN"
E:\Path\To\Music>youtube-dl -o "(title)s.1
Usage: youtube-dl [OPTIONS] URL [URL...]
youtube-dl: error: You must provide at least one URL.
Type youtube-dl --help to see a list of all options.
E:\Path\To\Music>
What's going on here? Why is the command not run properly as seen in the echo? Also is there possible a better way of doing this (tying a long command with argument to a short name) sorry for the low quality post just need this fast.
The script-parser tries to expand the variables:
%(playlist_index)s. %
%(ext)s" -x --audio-format "mp3" %
Which are likely undefined. Because there is nothing to expand, part of the command-line parameter is stripped before being passed to the youtube-dl program. Use double percent signs instead:
youtube-dl -o "%%(playlist_index)s. %%(title)s.%%(ext)s" -x --audio-format "mp3" "%~1"
Quoting and escaping
The percent sign (%) is a special case. On the command line, it does
not need quoting or escaping unless two of them are used to indicate a
variable, such as %OS%. But in a batch file, you have to use a double
percent sign (%%) to yield a single percent sign (%). Enclosing the
percent sign in quotation marks or preceding it with caret does not
work.

Error passing multiple commands to Cisco CLI via plink

I've gotten some help with an earlier part of this batch file, but now I'm having trouble with the final component.
I've tried a few things with no success. I tried changing the CRLF to LF which did nothing. I also tried rephrasing the commands a few ways but I am still not getting anywhere. The following is my main batch file.
#echo on
REM delete deauth command file
SET OutFile="C:\temp\Out2.txt"
IF EXIST "%OutFile%" DEL "%OutFile%"
plink -v -ssh *#x.x.x.x -pw PW -m "c:\temp\WirelessDump.txt" > "C:\temp\output.txt"
setlocal
for /f %%a in (C:\temp\output.txt) do >> "Out2.txt" echo wir cli mac-address %%a deauth forced
REM Use commands in out2 to deauth
plink -v -ssh *#x.x.x.x -pw PW -m "c:\temp\Out2.txt"
pause
Below this sentence is the command found in Out2 which I think is giving the actual trouble. The number of lines varies but they are all this particular command just with differing MACs.
wir cli mac-address xxxx.xxxx.xxxx deauth forced
If Out2 has only a single line it runs fine, no issues. But when there are multiple lines, it fails with an error stating that the Line has an invalid autocommand. It's almost as if it was reading it as one contiguous command. As I mentioned above I changed from CRLF to LF hoping IOS would like it better, but that failed. I've tried adding extra lines between the commands, and I've tried calling the login every time from that file.
I am hoping that there is a way to tailor the commands to pass all lines one at a time to keep this down to a minimum of files.
I had another thought but it is kinda/very clunky. If there was a way to output each of those MAC deauth commands to their own file in a saperate folder (out1, out2, out3), and have the BAT able to run all the randomly generated files in that folder so that each one is a separated plink session.
Let me know if I need to change/add/elaborate on anything. Thanks in advance for anything you guys are willing to help with. I appreciate it.
EDIT: Martin has pointed out what the limitation actually is. It appears to be a limitation on Cisco to accept blocks of commands through SSH. So I still have the same question really, I just need some help figuring a workaround to this issue. I'm thinking the multiple file solution I mentioned above may have some possibility. But I'm too much of a noob to know how to make that work. I'll update if I have any breakthroughs though. Thanks for any contributions!
It's actually a known limitation of Cisco, that it does not support multiple commands in an SSH "exec" channel command.
Quoting section 3.8.3.6 -m: read a remote command or script from a file of PuTTY/Plink manual:
With some servers (particularly Unix systems), you can even put multiple lines in this file and execute more than one command in sequence, or a whole shell script; but this is arguably an abuse, and cannot be expected to work on all servers. In particular, it is known not to work with certain ‘embedded’ servers, such as Cisco routers.
Though you can probably still feed multiple commands to Plink input:
(
echo command 1
echo command 2
echo command 3
echo exit
) | plink -v -ssh user#host -pw password > output.txt
Or you can simply use an input file:
plink -v -ssh user#host -pw password < input.txt > output.txt
Similar question: A way of typing multiple commands in cmd.txt file using PuTTY batch against Cisco
This works without cmd.exe and using files:
function Invoke-PlinkCommandsIOS {
param (
[Parameter(Mandatory=$true)][string] $Host,
[Parameter(Mandatory=$true)][System.Management.Automation.PSCredential] $Credential,
[Parameter(Mandatory=$true)][string] $Commands,
[Switch] $ConnectOnceToAcceptHostKey = $false
)
$PlinkPath="$PSScriptRoot\plink.exe"
$commands | & "$PSScriptRoot\plink.exe" -ssh -2 -l $Credential.GetNetworkCredential().username -pw "$($Credential.GetNetworkCredential().password)" $Host -batch
}
Usage: dont forget your exit's and terminal length 0 or it will hang
PS C:\> $Command = "terminal lenght 0
>> show running-config
>> exit
>> "
>>
PS C:\> Invoke-PlinkCommandsIOS -Host ace-dc1 -Credential $cred -Commands $Command
....
Sounds like your file 'Out2.txt' has only LF at end of line. Simple way to convert that to CRLF is to use MORE command and redirect output to a new file and then use the new file.
more Out2.txt > Out2CRLF.txt
I ran into the same issue when trying to pull the full list of ACLs on an ASA via plink in powershell.
Essentially, due to the abuse issue referenced in the documentation: https://the.earth.li/~sgtatham/putty/0.72/htmldoc/Chapter3.html#using-cmdline-m, I was getting inconsistent results in pulling the ACLs. Sometimes I would get 0, sometimes only 1 or 2, and sometimes I would get all of them. (I personally, had about a 1 in 5 success rate).
As I would occasionally be successful I used a while loop that would catch the unsuccessful attempts and retry. Just be sure to put some timing on the while loop to prevent it from spamming ssh connections too much.
It is not a good solution, but it worked as a last resort.

svnlook cat -t not working on windows (when I was creating .bat script)

I'm trying to write a .bat script as the pre-commit hooks in svn. However when I was trying to use the svnlook cat command with the -t option, it's not working. It kept telling me syntax errors. I tried everything including adding quotes, changing the -t option etc. However, if I remove the -t option, it doesn't report syntax errors.
So this is the error scripts:
SET REPOS=%~1 (I want to remove the quotes of the path)
SET TXN=%2
"C:\Program Files (x86)\VisualSVN Server\bin\svnlook.exe" cat -t %TXN% %REPOS% myworkingdir/txtIwanttoread
If I do the following, they are all fine:
SET REPOS=%~1 (I want to remove the quotes of the path)
SET TXN=%2
"C:\Program Files (x86)\VisualSVN Server\bin\svnlook.exe" cat %REPOS% myworkingdir/txtIwanttoread
OR
SET REPOS=%~1 (I want to remove the quotes of the path)
SET TXN=%2
"C:\Program Files (x86)\VisualSVN Server\bin\svnlook.exe" cat -r 28 %REPOS% myworkingdir/txtIwanttoread
Somebody please help me!! Thanks!
Never mind everybody, I think I just figured it out myself. We should use SET TXN=%~2 to eliminate the quotes. Also even if I did that, the stupid batch puts a space at the end of the variable TXN. This is what causes the problem. So the script should look like:
SET REPOS=%~1 (I want to remove the quotes of the path)
SET TXN=%~2
SET TXN=%TXN: =% (deblank)
"C:\Program Files (x86)\VisualSVN Server\bin\svnlook.exe" cat -t %TXN% %REPOS% myworkingdir/txtIwanttoread

How to include pipe character in an argument to a batch file from a bash script?

I have a shell script that I want to execute this line:
qtvars.bat vsstart "qt.sln" /BUILD "Debug|Win32"
This works fine (though I had to modify qtvars.bat, but that's beside the point). The problem is that I want the command to execute to be in a variable:
EDIT: This doesn't work either, if I type it into bash. Previously I was typing it into cmd.exe, which hardly made for a fair comparison.
command="qtvars.bat"
args="vsstart"
$command $args "qt.sln" /BUILD "Debug|Win32"
Now it chokes on the pipe! I get this message:
'Win32' is not recognized as an internal or external command,
operable program or batch file.
I've tried a bunch of forms of escaping the quotes and/or pipe, all to no avail. Interestingly, it works when it's an executable rather than a batch file, e.g.:
command="devenv.exe"
args=""
$command $args "qt.sln" /BUILD "Debug|Win32"
Thanks for any ideas.
I know you "escape" the pipe character in a batch file with the ^ character, so...
echo ^| Some text here ^|
Would display...
| Some text here |
I don't know whether that would help you in this instance? Maybe try prepending each pipe character with a ^ and see what happens? :-)
This is a classic case of double-escaping, where both bash and CMD.EXE need to be instructed to ignore the special | (pipe) character.
Try the following:
$command $args "qt.sln" /BUILD '"Debug|Win32"'
This will be the equivalent of you typing, at a CMD.EXE prompt:
qtvars.bat vsstart qt.sln /BUILD "Debug|Win32"
Using the above, you are essentially forcing the passing of the double-quotes on to CMD.EXE (instead of bash eating them away.) The outermost single quotes instruct bash not to interpret or touch in any way what's inside them; the inner double-quotes instruct CMD.EXE to ignore any special characters (the pipe in this case) within.
Alternatively, you can also try:
$command $args "qt.sln" /BUILD 'Debug\|Win32'
This should be the equivalent of you typing, at a CMD.EXE prompt:
qtvars.bat vsstart qt.sln /BUILD Debug\|Win32
Note the use of single quotes (!), which ensure that bash will not interpret the \ (and, instead, will pass it as-is to CMD.EXE.)
Here's another solution (workaround?) I've found:
first, ensure an environment variable defines the pipe character, for example:
set PIPE="|"
later, run the command specifying the above defined environment variable name:
"c:\(...)\devenv.com" foo.sln /build Debug%PIPE%Win32
That does the job even if there are multiple wrappers between the caller and the callee. I'm now using it with a very long chain of wrappers:
Python/Linux -> VirtualBox guest's executeProcess -> Cmd/Windows -> devenv.com
(cross posted to: How to pass a quoted pipe character to cmd.exe?)
Escaping a piping character in the Windows scripting language is done with a caret (^). I just had to do this the other day. I know this is old, but I thought I would post what I found in case others ran across this, like I did.
I'd consider going the easy route, and passing a placeholder-token instead - "$P", and then replace it within the CMD/Batch file; e.g. using the 'UnxUtils' SEd command to do the replacement:
For /F "usebackq delims=" %%r in (`Echo %Cmd% ^| sed -e "s/$P/|/g"`) do #Set Cmd2=%%r
REM Now run the command, with the proper pipe symbol in place
%Cmd2%
So having passed the command arg/CMD script args - "git status $P wc -l".
Interesting! What does escaping the | do?
Do these work?
echo "Debug|Win32"
echo "qt.sln" /BUILD 'Debug|Win32'

Resources