echo %cd% alias does not respond as it should - cmd

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)

Related

Why does my PWD variable not retain its value?

I have the following code:
PWD="$(pwd)"
echo $PWD
cd
echo $PWD
If I run this from within /home/USER/sandbox, the output of the above is:
/home/USER/sandbox
/home/USER
Why does PWD not preserve its value? Is there any way to get it to preserve its value?
The key is that you called the variable PWD. This is one of several all-uppercase names used specially by Bash:
PWD
The current working directory as set by the cd command.
After each cd command, $PWD is updated to match.
I recommend you use lower-case for your variable names, to avoid surprises like this.
If I type all of those commands into the command line, I find that WD does "preserve it's value".
However I've run into this issue multiple times with various scripts and the root cause is one shell session (and/or a script) doesn't transfer its environment to another. Common solutions include doing everything I want to do in one script and saving values in a file for later use.
Hope this helps.

How can I trick bash to think I ran a script from within the directory where the binary is located?

I have a binary (emulator from the Android SDK Tools) that I use frequently. I've added it to my $PATH variable so that I can easily run the command with solely emulator.
However, it turns out that the binary uses relative paths; it complains if I run the script from a different directory. I'd really like to run the command from any folder without having to cd into the directory where the binary lives. Is there any way to get the script/bash into thinking I ran the command from the directory that it's located in?
A function is an appropriate tool for the job:
emu() ( cd /dir/with/emulator && exec ./emulator "$#" )
Let's break this down into pieces:
Using a function rather than an alias allows arguments to be substituted at an arbitrary location, rather than only at the end of the string an alias defines. That's critical, in this case, because we want the arguments to be evaluated inside a subshell, as described below:
Using parentheses, instead of curly brackets, causes this function's body to run in a subshell; that ensures that the cd only takes effect for that subshell, and doesn't impact the parent.
Using && to connect the cd and the following command ensures that we abort correctly if the cd fails.
Using exec tells the subshell to replace itself in memory with the emulator, rather than having an extra shell sitting around that does nothing but wait for the emulator to exit.
"$#" expands to the list of arguments passed to the function.
Add an alias (emu) to your ~/.bashrc:
alias emu="(cd /dir/with/emulator; ./emulator)"
I would look into command line aliases.
If you are in linux and using bash you can go to ~/.bash_profile and add a line such as:
alias emulator='./path-to-binary/emulator"
On windows it's a little different. Here is an example on how to do a similar thing in windows.

How do I get and print value of an environment variable?

I want to print value from a Windows environment variable, say, path or errorlevel, I've tried this but it doesn't work. Output this in my console:
(without consider spaces/tabs which it outputs):
echo %PATH
%PATH
Makefile:
PATH=$(PATH);\nonesuch
all:
echo %PATH%
command-line:
nmake /E
How do I fix it?
NOTE: Visual Studio's binary path is in my PATH variable, that's why I'm calling this outside VS console
The percent sign % has special meaning in Makefiles.
In order to perform the Windows batch-file substitution, you need to escape it like this:
echo %%PATH%%
This seems to work too:
"echo %PATH%"
Another option is to perform the substitution on the Make side, but that's a different thing:
echo $(PATH)
To view your path, just try out this
echo $PATH

Calling vcvars from bash script

I need to call vcvars32.bat and vcvars64.bat from within the same bash script (msys) which builds different version of my application.
The problem is that, even if I am able to call the batch files with the cmd.exe command, once it returns the Visual Studio variables are obviously not set.
I cannot call vcvars from an external batch file (like msys.bat) which call the bash script, as I need in the same script to call both of them sequentially.
So, is there any way to call vcvars in order to properly set the variables in the bash script while running?
One way to solve this is to run your commands from within the vcvars environment, rather than trying to export it back to the bash side. That's the approach we've chosen for our project.
The main problem is that vcvars*.bat doesn't accept commands to execute in the environment, so a little bit of trickery with cmd is required. So I came up with a simple Bash script called vcvars_env_run.sh that accepts arbitrary arguments and forwards them to a cmd.exe on which vcvars64.bat has been called. The bulk of the work is figuring out how to properly forward quoted arguments, and things like &&, ||, return codes, etc.
I've uploaded the script and some examples at https://github.com/kromain/wsl-utils
You might need to tweak it a little to switch between vcvars32.bat and vcvars64.bat, but hopefully it helps for what you're trying to do.
The POSIX shell export -p prints the values of all environment variables such that an eval of the output recreates those values. The idea is to invoke this from a subshell after vcvars*.bat has run and to eval the captured output in the top-level script.
A Cygwin environment variable setup script can obtain the results of vcvars*.bat as follows:
eval "$($(cygpath "$COMSPEC") /c vcvars_export "$vcvars_bat" "$(
cygpath -w "$SHELL")")"
where vcvars_bat contains the path of the relevant vcvars*.bat file. You will find this value e.g. in the target of the x64 Native Tools Command Prompt for VS 2019.lnk file, which can be read with readlink -t. (Note also that the vcvarsall.bat script allows specification of the compiler and SDK version to use, useful when precise control is needed).
The local vcvars_export.bat file contains
#echo off
call %1 > nul
"%2" -c "export -p"
Limitations of the Cygwin native process invocation subsystem (argument quoting is done heuristically) make this auxiliary file necessary.
What you need to do is to use the command: "call" in your batch script. So it could look something like:
call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\vcvars32.bat"
echo DevEnvDir set to: %DevEnvDir%
If you don't use the "call" then the script will exit after the vcvars32.bat exits and won't run any other command.

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