Batch Script - Using Variable with SCP command - windows

I have a simple batch script which transfers a file filename to a remote location destination using SCP.
Using scp filename destination works perfectly fine, however adding variable var doesn't work.
Code snippet:
set /p "var=filename"
echo %var%
echo scp "%var%" destination
scp "%var%" destination
Results:
filename
scp "" destination
: not a regular file
The variable is not used or recognized by the second echo and scp.
Is there something I'm missing from using the variable properly in echo and scp?
Note: Code snippet is in an if statement
Solution:
Need to use delayexpansion, and use !var! instead of%var%
See here: windows batch SET inside IF not working

There is no problem with the snippet you posted.
But these lines will fail in the way you describe if these lines are within a parenthesized codeblock.
If this is the case then you must change the code to use delayed expansion.
See setlocal/? and set/? for details and documentation.

Related

echo %cd% alias does not respond as it should

I have created and alias named pwd for echo %cd% (#DOSKEY pwd=echo %cd%). I have saved it in bat file and configured it to autorun with command processor.
Now whenever I run the command pwd in my command processor it returns with the C:\windows\system32 no matter in which path I am currently in. whereas when I run the echo %cd% it returns the right path I am in.
How do I solve this problem? Is it because of the parameter I am passing to echo? This parameter should update according to the path I am going in. It seems it updates just once when the command prompt is loaded with aliases.
That is because %cd% is expanded during the definition of the macro, not when it is executed.
From a batch file, you should use:
#DOSKEY pwd=echo %%cd%%
If defining from the command line, the expansion rules are different, so you would need something like:
DOSKEY pwd=echo %^cd%
But there is an even simpler method that works in all cases. The CD command without arguments simply lists the current directory. Just enclose the command in parentheses to prevent arguments from being passed.
#DOSKEY pwd=(cd)

How do I conditionally turn #ECHO ON/OFF in a Windows batch file?

I have a batch file that can be run locally or on the build server to do some kind of interesting job. On the local machine, I want #ECHO OFF so that your console isn't full of debug strings. On the build server, I'd rather have #ECHO ON so that failures can be investigated.
The build server context can be determined if a special environment variable exists (TEAMCITY_PROJECT_NAME). So, I thought I could do something like
IF DEFINED TEAMCITY_PROJECT_NAME #ECHO ON ELSE #ECHO OFF
But, that's not working, I get the IF statement echoed along with everything else... any thoughts?
The command is not actually named #echo. The # is an optional flag valid at the beginning of a statement to indicate that echo is suppressed for that statement. So using the # on each reference to the echo command will hide the echo command itself, but not the if command that precedes it.
But the issue that is actually causing your command to fail to operated as expected is that the first echo command will slurp up the rest of the tokens on the line as its arguments, so the else echo off part will not be interpreted by CMD. Since CMD.EXE echoes by default it prints the if command, and then either executes a single echo command or nothing. Since the # does have meaning at the start of the statement that is the body of the if, neither echo command would be printed.
In general, the solution to that is to use parenthesis to delimit the command boundaries. However, since echo is on by default and you really only want to suppress it if TEAMCITY_PROJECT is not define, we can say that directly.
#IF NOT DEFINED TEAMCITY_PROJECT_NAME ECHO OFF
I've left a single # at the beginning to suppress echo of this line, and as a result this line will not appear in your server's logs.
Related note
The echo state also applies to an interactive session. Typing echo off at an interactive CMD session prompt will cause it to stop showing the prompt. Which is a tad disconcerting, if not expected. Typing echo on will restore normal behavior.
More on Parsing
(I've edited the earlier section for clarity, and added this section to attempt to document what is really happening.)
The CMD.EXE program that interprets .BAT and .CMD scripts, and provides the interactive command prompt in modern Windows is surprisingly well documented while effectively being undocumented. My attempts to search for an official document explaining that the at-sign has this effect and exactly where it can be used have been largely unsuccessful.
It is clear from experimentation that the at-sign is parsed and interpreted if it appears as the first non whitespace character of a command. I've tried to express that by using the phrase "beginning of a statement" above.
As far as I can tell there is no formal grammar published for CMD's language. But we do know from the documentation for CDM itself (type cmd /? to a prompt) as well as if /? and the built-in help text for other "interesting" built-in commands that there are rules that are followed when CMD parses its source text.
The start of a command appears to be at the beginning of a line, or after the conditional of an if, after the else, or after an open parenthesis (. Once the at-sign has been recognized, it applies to (most) of the balance of that command.
Try the following batch file yourself, and play with moving the at signs around and you'll quickly get the sense that the rules are hard to state precisely:
rem this remark will echo
#rem this one will not
# rem neither will this
#rem nor this one
#rem the if command (and else) will echo, but not either echo command
if exist q17241089.bat ( # echo saw q17241089.bat ) else # echo foo
if not exist q17241089.bat ( # echo no q17241089.bat ) else # echo bar
# rem none of the following command is echoed
# if exist q17241089.bat ( # echo saw q17241089.bat ) else # echo spam
When run on my Win 7 Pro I see:
C...>
C...>q17241089.bat
C...>rem this remark will echo
C...>if exist q17241089.bat () else
saw q17241089.bat
C...>if not exist q17241089.bat () else
bar
saw q17241089.bat
C...>
As with most of the fine details of BAT files, there is a mystery underneath any surface you scratch.
set parentheses (see docu...):
IF DEFINED TEAMCITY_PROJECT_NAME (#ECHO ON) ELSE #ECHO OFF
Well, it seems that ECHO is on by default, so you'll get the IF statement output anyway you test that conditional. You should start with
#ECHO OFF
And add your conditional as another statement to evaluate
#ECHO OFF && IF DEFINED TEAMCITY_PROJECT_NAME #ECHO ON
As noted in earlier responses, ECHO is on by default. An alternative way of achieving the same behavior is:
#if "%TEAMCITY_PROJECT_NAME%" == "" #echo off

Why I am getting "Echo is on" when trying to print a variable in batch

I tring to excute a simple batch file scripts :
echo %1
set var = %1
echo %var%
When I am running it in XP, it is giving me expected output, but When I am running it in Vista or windows 7, I am getting "Echo is On" when trying to print (echo) value.
Below is the output of program :
G:\2012>abc.bat 1
G:\2012>echo 1
1
G:\2012>set var = 1
G:\2012>echo
ECHO is on.
G:\2012>
Get rid of the spaces in your set expression. There can and should be no spaces on either side of the equal sign (=)
set var=%1
BTW: I usually start all my batch files with #echo off, and end them with #echo on too, so I can avoid mixing code with the output of the batch file. It just makes your batch file output a little nicer and cleaner.
I had this error when I tried to do an echo without any value and redirect to a file using Python. Looks to be a hidden troubleshooting feature in the echo command.

using the DOS start command when passed arguments have quotes

I have a question about the DOS start command.
I have already read this topic:
Using the DOS “start” command with parameters passed to the started program
Using the "start" command with parameters passed to the started program
but my question is a little different.
I have this problem: I need to pass paths that need to be quoted.
For example, if path have no quotes this works fine:
start "" app.exe -option c:\myapp\myfile.txt
but if path have double quotes it doesn't works.
I have this line in my BATCH file:
start "" myapp.exe -option %mypath%
and when %mypath% contains double quotes (paths that have spaces or other characters in names) the start command returns very strange results.
Thanks
Sandro
Normally it's not a problem to use parameters there with quotes, but you get problems if your app-path has also quotes.
Then you need to add an extra CALL statement.
start "" app.exe -option c:\myapp\myfile.txt - Works
start "" app.exe -option "c:\myapp\myfile.txt" - Works
start "" "app.exe" -option c:\myapp\myfile.txt - Works
start "" "app.exe" -option "c:\myapp\myfile.txt" - Don't works
start "" CALL "app.exe" -option "c:\myapp\myfile.txt" - Works
This might help, but it is a bit way round about method and slight modification may required to suit your need.
The idea is to:
Dump the environment variable which has quotes to a text file with a predefined name. Like:"set mypath2 > withQt.bat"
Use windows power shell or some third party tool to find and replace quotes in that file.
Create another text file (one time step only) containing string "Set "
Use copy command to append the file mentioned in step2 with the file created in step3 and create a batch file with a predefined name. Like: copy base.bat + withQt.bat withtqt.bat
Run the batch file, which creates another/replaces the environment variable with value without quotes.
Sorry, I couldn't get something more elegant at this time.

Batch file equivalent of Unix parameter expansion with quotes

There have been a lot of questions asked and answered about batch file parameters with regards to the %*, but I haven't found an answer for this.
Is there an equivalent syntax in batch files that can perform the same behavior as "$#" in Unix?
Some context:
#echo off
set MYPATH=%~dp0
set PYTHON=%MYPATH%..\python\python
set BASENAME=%~n0
set XTPY=%MYPATH%..\SGTools\bin\%BASENAME%.py
"%PYTHON%" "%XTPY%" %*
This is the .bat file that is being used a proxy to call a Python script. So I am passing all the parameters (except the script name) to the Python script. This works fine until there is a parameter in quotes and/or contains spaces.
In shell scripts you can use "$#" to take each parameter and enclose it in quotes. Is there something I can do to replicate this process?
Example calls:
xt -T sg -t "path with possible spaces" -sum "name with spaces" -p <tool_name> -o lin32 lin64 win32 <lots of other options with possibilities of spaces>
The command/file xt simply contains the code listed above, because the actual executable is Python code in a different folder. So the point is to create a self-contained package where you only add one directory (xbin directory) to your path.
I'm not sure what the cleanest solution is, but here is how I worked around the problem:
setlocal EnableDelayedExpansion
for %%i in (%*) do set _args= !_args! "%%~i"
echo %_args%
%_args% will now contain a quoted list of each individual parameter. For example, if you called the batch file as follows:
MYBATFILE "test'1'file" "test'2'file" "test 3 file"`
echo %_args%
will produce the original quoted input.
I needed this for CMD files that take unfriendly file or directory names and pass them to Cygwin Bash shell scripts which do the heavy lifting, but I couldn't afford to have the embedded single quotes or spaces lost in the transition.
Note the ~i in %%~i% which is necessary to remove quotes before we apply quotes. When a parameter containing spaces is passed (e.g., "test 3 file" above), the CMD shell will already have applied quotes to it. The tilde here makes sure that we don't double-quote parameters containing spaces.

Resources