Exporting a variable from a Windows batch file to Cygwin - batch-file

I want to initialize my Cygwin environment with a variable coming from a batch file
#set myvar=test
%BASH% --login -c "set"
REM hope to see myvar
So I want myvar with its value eventually be available in bash.

You can have the batch file append your variable to your bash.bashrc file to create bash environmental variables, like so:
export croot=/cygdrive/c
Then you access that croot variable like so
export cc=$croot/CC
or
alias cdcc='cd $croot/CC'
The path on my machine is C:\cygwin\etc\bash.bashrc ... yours may differ.
Note that the variable won't be available in running cygwin sessions, only new ones.

Related

Pass multiple variables to binary

In unix command line you can do this
tempvar=ABC mybinary
apparently you can do the same in Windows batch, but in case you need multiple assignments to pass, export in unix would do the trick. How could you pass multiple variables to mybynary in a Windows Batch script?
1. Information about Windows commands and Windows command processor syntax
There can be executed help in a command prompt to get output an incomplete list of Windows commands with a brief description. Any Windows command can be executed with /? as argument to get output the usage help for the command. The execution of cmd /? results in output of the usage help of Windows command processor cmd.exe which is the Windows equivalent for man sh (or man bash, man dash, man ksh, man zsh, etc.) in a Linux terminal window.
For most Windows commands, but not all of them, it is also possible to run help with the command name as argument. help set and set /? output both the usage help of the command to define environment variables.
There is additionally:
the Microsoft documentation about the Windows commands
the A-Z index of Windows CMD commands by SS64
the Windows CMD Shell How-to guides and examples by SS64
SS64 offers also comprehensive documentations for other scripting languages on Windows, Linux and Mac.
There are two types of Windows commands:
the internal commands of cmd.exe like echo, copy, set
the so called external commands like chcp, find, robocopy
The external Windows commands are executables in directory %SystemRoot%\System32 with file extension .com like chcp.com (rare) or file extension .exe like find.exe, robocopy.exe and where.exe (most external Windows commands).
There are on 64-bit Windows two system directories:
%SystemRoot%\System32 contains the 64-bit executables and dynamic linked libraries.
%SystemRoot%\SysWOW64 contains the 32-bit executables and dynamic linked libraries.
The Windows commands usually exist in both system directories as 32-bit and 64-bit executable on 64-bit Windows. But there are some executables existing only as 64-bit executables.
That is important to know if a 32-bit application starts on 64-bit Windows the Windows command processor cmd.exe to process a batch file because of the File System Redirector starts in this case 32-bit %SystemRoot%\SysWOW64\cmd.exe and all commands found via the environment variables PATHEXT and PATH in folder %SystemRoot%\System32 being by default the first folder path in system environment variable PATH are in real searched and executed from directory %SystemRoot%\SysWOW64 in the 32-bit execution environment on 64-bit Windows.
In a command prompt window are entered by a user a command usually with just its file name and so the Windows command processor has to search for a suitable file to execute. For details about this process read: What is the reason for "X is not recognized as an internal or external command, operable program or batch file"?
In a batch file can be used also only the file name of an external Windows command, but it is advisable to specify them with full qualified file names for the following reasons:
The batch file an external command specified like %SystemRoot%\System32\find.exe instead of just find are more fail safe and secure as the batch file does not depend on the environment variables PATHEXT and PATH defined outside of the batch file which are quite often modified by programs and users, especially the environment variable PATH.
The batch file is executed faster as the Windows command processor has not to search in file system for the executables.
The external Windows command where can be used to find out if a Windows command is an internal command or an external command. The execution of where set in a command prompt window results in output of an error message (hopefully) while where find results in output of file qualified file name of find (hopefully found first in %SystemRoot%\System32 with file extension .exe).
2. Define one or more environment variables for an executable
The command to define environment variables on Windows is SET. So this command must be used to define an environment variable which an executable evaluates on execution. An environment variable like tempvar can be defined as follows:
set tempvar=ABC
set "tempvar=ABC"
The second syntax is highly recommended, but requires enabled command extensions which is the case by default, but which does not mean that command extensions are always enabled. Please read my answer on: Why is no string output with 'echo %var%' after using 'set var = text' on command line? There is explained in full details why set "variable=value" is the recommended syntax.
The environment variable(s) evaluated by an executable can be defined on separate lines before execution of the executable or on same command line.
Definition of the environment variable and execution of the executable on separate command lines:
set "tempvar=ABC"
mybinary
Definition of the environment variable and execution of the executable on one command line:
set "tempvar=ABC" & mybinary
Single line with multiple commands using Windows batch file explains the operator & used in the single command line variant.
A batch file writer should avoid replacing one of the predefined Windows environment variables, except a predefined environment variable should be intentionally redefined in a batch script.
3. Define one or more environment variables just for an executable
Environment variables defined inside a batch file for an executable are still defined after the executable terminated itself. Therefore the environment variables are readable for any other executable started next by cmd.exe in same batch file or even after batch file processing finished depending on how cmd.exe was started for processing the batch file and the execution environment defined by the batch file itself.
The Windows command processor uses the Windows kernel library function CreateProcess to run an executable like any other Windows application capable running an executable. cmd.exe uses always NULL for the CreateProcess function parameter lpEnvironment which results in CreateProcess making a copy of the current environment variables list of cmd.exe for the executable started next.
The commands SETLOCAL and ENDLOCAL can be used in a batch file to define the environment variables evaluated by an executable just for the executable as the code below demonstrates.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem The two command lines above define completely the execution environment for the
rem batch file and so the batch file does not depend anymore on settings outside of
rem the batch file.
rem Define MyVariable1 and undefine MyVariable2
set "MyVariable1=Demo"
set "MyVariable2="
rem Verify that with an output of all environment variables of
rem which name starts with the string MyVariable with their values.
echo/
echo My variables defined in batch script at top:
echo/
set MyVariable
setlocal
set "MyVariable1=Other value for execuable"
set "MyVariable2=Defined also for executable"
echo/
echo My variables defined for mybinary:
echo/
set MyVariable
if exist mybinary mybinary
endlocal
echo/
echo My variables defined after execution of mybinary:
echo/
set MyVariable
endlocal
echo/
echo My variables as defined outside of the batch file:
echo/
set MyVariable
echo/
pause
I recommend to read this answer in addition to execution of setlocal /? and endlocal /? in a command prompt window to get full knowledge on what is done by these two commands in background.
4. Referencing files in batch file directory with full path
The Windows command processor cmd.exe can be executed for processing a batch file from within any directory which means the current working directory can be any directory. For that reason it is advisable to reference other files in the directory of the batch file with full path and with file extension instead of just the file name.
The usage of just mybinary results in searching in current working directory for a file with name mybinary having one of the file extensions as listed in environment variable PATHEXT if the environment variable NoDefaultCurrentDirectoryInExePath is not defined. In other words the successful execution of mybinary depends on execution environment settings defined outside of the batch file which is not good.
So it is advisable to use "%~dp0mybinary.exe" in the batch file to reference the executable with full qualified file name whereby %~dp0 references the drive and path (can be also a UNC path) of argument 0 which is the full folder path of the batch file always ending with a backslash and therefore concatenated without an additional backslash with file name mybinary.exe.
The usage of "%~dp0mybinary.exe" has following advantages regarding to execution of this executable:
It does not matter anymore how the environment variable PATHEXT is defined.
It does not matter anymore if the environment variable NoDefaultCurrentDirectoryInExePath is defined or not.
It does not matter anymore what is the current working directory on execution of the batch file as long as the executable is good coded and does not expect that the directory containing the executable is the working directory to access other files in that directory.
For completeness regarding usage of %~dp0 see also:
What is the reason for batch file path referenced with %~dp0 sometimes changes on changing directory?

How to fetch the environment variables that are set for the current instance of cmd.exe?

I have a cmd batch script that sets some variables. I tried the command SET, but it lists all the environment variables, including the system default ones (or Global ones). I am interested in knowing exactly the ones which are being set inside that script. Is there any way to do that from the command line?
Also, let's say I exported all the environment variables in a text file. Can I set them all at once in a new cmd.exe instance by providing the file path? Or, looping through each one of them is the only option?
Edit: I can't modify the original batch script and don't have any control over it's future changes.

How to make my Linux C program accessible from bash

Say I made and compiled a small program in C to count the bytes of a file, called filebyte. To run it I would use ./filebyte
Now I want to make it universal on bash, like for example to run a php file, I would use bash command php file.php, same way I would like to run my program, filebyte filename.
How do I do this?
Thanks!
I often create a bin/ directory in my home directory, for small custom applications.
You then need to add that directory to your PATH, which is a list of colon-separated paths that your shell searches for executables when you type a name on thr command line.
This is usually accomplished by putting this in your ~/.bashrc file:
PATH="$PATH:~/bin"
Check the environment variable PATH and put the executable in one of the directories listed. You can also put it in a custom directory and then append it to PATH. You can check it by executing printenv PATH
If you want it for your current active shell alone, do
export PATH=$PATH:</path/to/file>
For permanently making the file available add the above line to ~/.bashrc
Why add it in PATH variable, man bash says why,
PATH The search path for commands. It is a colon-separated list of
directories in which the shell looks for commands (see COMMAND
EXECUTION below). A zero-length (null) directory name in the
value of PATH indicates the current directory. A null directory
name may appear as two adjacent colons, or as an initial or
trailing colon. The default path is system-dependent, and is set
by the administrator who installs bash. A common value is
''/usr/gnu/bin:/usr/local/bin:/usr/ucb:/bin:/usr/bin''.

Save an environment variable without using /bin/bash

I have a program that creates a environment variable called $EGG with this code
memcpy(buff,"EGG=",4);
putenv(buff);
system("/bin/bash");
And the value of buff is used to create an environment variable, and I use it through $EGG variable, but for use it I see that I must use the call system("/bin/bash");. Otherwise, if I don't use /bin/bash call I don't find my $EGG variable.
Is there a way to save my environment variable without calling /bin/bash?
Short answer: You cannot modify an existing environment the way you try.
Background: The program you use to create the environment variable EGG in gets its own environment on start-up (typically as copy of the environment of the process that starts the program). Inside the program's very own environment EGG is created.
When a program ends its environment is also gone and with it would had been created in there.
To modify an environment programmatically do not write a (C) program but use a script.
Using bash this could look like this:
#!/bin/bash
export EGG=4
save this as for example set_egg_to_4.sh and adjust the files mode do be able to execute the it:
$ chmod +x set_egg_to_4.sh
Then run the script:
$ ./set_egg_to_4.sh
and test for EGG, by doing
$ echo $EGG
4
To "permanently" set an environment variable, add it to your .bash_profile file.
export EGG=4
This file is sourced each time you start a login session, so that EGG is added to your environment each time. Any that inherit (directly or indirectly) from this shell will also have EGG in its environment.
There may be other files on your system that are sourced immediately on startup, so that a variable set in such a file is available to all processes (regardless of the user). (One I'm think of is /etc/environment.)

Tracing Batch Variable

I have this batch which executes on the server computer. There is a scheduled job which runs the batch. The Batch detects a particular file and then it executes an sqlcmd like below:
if not exist %TRIG_FILE% goto No_Triggers
sqlcmd
-S %WSL_SERVER%
-d %WSL_DATABASE%
-E
-Q "DECLARE #RES integer;DECLARE #RET varchar(1);DECLARE #MSG varchar(65);EXEC Ws_Job_Release 1,'Release Job Unlock Batch','All',0,0,'Unlock_Batch',#RET OUTPUT,#MSG OUTPUT,#RES OUTPUT"
My question is - how did the batch know what the %WSL_SERVER% variable is, because when I look at the script, there is nowhere in there which sets the %WSL_SERVER% variable.
This is the first time I'm reading a .bat script, I know a fair bit of programming, but I can't see how that variable was passed into this script so that it knows which server. There's no other batch calling this, it's from the batch run by the scheduler.
thanks
gemmo
Most likely the WSL_SERVER and WSL_DATABASE are global environment variables initialised every time with your Windows session. That means they exist (are defined) in every CMD session and thus in every batch script. You can open a new Command Prompt window and issue this command
SET WSL
which will (try to) display all environment variables, whether global or local, whose names start with WSL. My guess is the output will show you at least the two WSL variables used in your script.
There is a number of global variables pre-defined and maintained by the OS. Yours, however, are probably user-defined (just my guess based on the fact that my system does not have them). User-defined variables can be created by third-party software or your own (maybe someone else's) batch scripts, as well as with a standalone invocation of the SETX command:
SETX VarName "Value"
You can use that command to change the value of any of your variables globally. Note that you can also change that value temporarily only, for the duration of the script, using the SET command as usual, if global change is undesirable:
SET "VarName=Value"

Resources