MingW64 path environment variable is automatically removed whenever I set it [duplicate] - cmd

This question already has answers here:
What is the reason for "X is not recognized as an internal or external command, operable program or batch file"?
(4 answers)
Closed 1 year ago.
Whenever I set MingW64 PATH environment variable it is automatically removed.
I also tried using cmd to set the PATH
setx path "%path%;C:\msys64\mingw64\bin"
But even after this command if I try
g++ --version
I still gets this error
'g++' is not recognized as an internal or external command, operable program or batch file.
I am using Windows 10
What should I do?
Thanks in advance

To add a new location to your User Environment Path value string, (or create a new value if one did not already exist), for use in future cmd.exe sessions, but not in the current one, you could use something like this:
#Echo Off
Rem Please note: The Path variable stringtype is REG_EXPAND_SZ.
Rem This means it will auto expand contained variables within the location string.
Rem It is therefore recommended that you include those possible.
Rem But please be aware, when you include them below, double all percent characters.
Rem Enter your new User Path string entry here:
Set "NewString=%%SystemDrive%%\msys64\mingw64\bin"
Set "Reg=%SystemRoot%\System32\reg.exe"
Set "Key=HKCU\Environment"
Set "StX=%SystemRoot%\System32\setx.exe"
%Reg% Query "%Key%" /V Path 1>NUL 2>&1 && (For /F "EOL=H Tokens=2,*" %%G In ('
%Reg% Query %Key% /V Path 2^>NUL') Do %StX% Path "%NewString%;%%H" 1>NUL
) || %Stx% Path "%NewString%;" 1>NUL
For the current cmd.exe session only, you'd do it more like this:
#Echo Off
Path "C:\msys64\mingw64\bin;%Path%"
You could therefore, if you wish, append this as the next line in the upper script, to allow its use in the current instance, and for all future ones:
Path "%NewString%;%Path%"

Related

How do I add a directory to User Environment Variables (PATH) without causing duplicates?

I'm trying to set up a script that will install python automatically, and I'm stuck on setting up the user path. I have only a vague clue about what I'm doing here so please excuse me if I'm using any terms incorrectly.
I'm trying to set the environment variables using setx path "%PATH%;%LOCALAPPDATA%\Programs\Python\Python310"\ but I've run into several issues.
I finally have this command not failing because of 'multiple default arguments' or something but now when trying to set PATH, I get duplicate entries.
If originally %PATH% gave me '\path1;\path2', and I run setx path "%PATH%;\path3", %PATH% outputs '\path1;\path2;\path1;\path2;\path3',
when I expected to have '\path1;\path2;\path3'
As per what I've been reading from other answers, I think %PATH% gives you the combined SYSTEM and USER paths, but setx path modifies the USER path only. So everytime I run setx path I'm adding the system variables again.
I just want to add my python.exe location to the user path variable in a .bat script without this duplicating issue. Does anyone have a working solution?
#ECHO OFF
SETLOCAL
SET "python=%%USERPROFILE%%\AppData\Local\Microsoft\WindowsApps"
ECHO %path%>u:\pp.txt
FOR /f "tokens=1,2,*" %%u IN ('reg query HKCU\Environment') DO IF "%%u"=="Path" (
FIND /v "%python%" "u:\pp.txt" >NUL
IF NOT ERRORLEVEL 1 (
ECHO CHANGE path
ECHO SETX PATH "%%w;%python%"
)
)
DEL u:\pp.txt
GOTO :EOF
I used a path that I have installed as python. Note that the % need to be doubled.
Write the current path to a tempfile (u:\pp.txt is simply on a RAMDRIVE for me)
Read the environment data from the registry, tokenise and select for the first item in %%u being Path. Its value will be in %%w.
See whether the "python path" is already in the path; if not, errorlevel will be 1 so execute the setx.
I merely echoed the setx as I'm not going to change the registry. If the command echoed appears correct, remove the echo to actually execute the setx.
It may be an idea to also set the path in the current environment, as setx changes the variable's value for future instances, not for the current one.
===== Revision ==== in the light of comments:
#ECHO Off
SETLOCAL
SET "python=%%USERPROFILE%%\AppData\Local\Microsoft\WindowsApps"
ECHO %path%>u:\pp.txt
FOR /f "tokens=1,2,*" %%u IN ('reg query HKCU\Environment') DO IF /i "%%u"=="Path" (
FIND /v "%python%" "u:\pp.txt" >NUL
IF NOT ERRORLEVEL 1 (
SETLOCAL ENABLEDELAYEDEXPANSION
SET "xpath=%%w;%python%"
SET "xpath=!xpath:~159!"
IF DEFINED xpath (ECHO PATH too long) ELSE (
ECHO CHANGE path
ECHO SETX %%u "%%w;%python%"
)
ENDLOCAL
)
)
DEL u:\pp*.txt
GOTO :EOF
Fixes:
Comparison in for ...%%u made case-insensitive.
Length of resultant user-path variable checked. I used a value of 159 for testing, 1022 for real-world.
variable name being setx'd will be identical to that retrieved from the registry. (For me, it's Path (W11 22H2) - My editor helpfully changes any batch keyword followed by a space to upper-case)

Append to System PATH variable value using a batch file

I want to create a batch file to add the current directory to my System variable PATH, (not my User variable).
When I use:
SETX /M PATH "%CD%;%PATH%"
it does the needed thing. However, I get an error message:
data being saved is truncated to 1024 characters.
When I check the System variable using the GUI, I saw that User Path is getting added to the System Path. As a result, the System Path has duplicated entries.
I tried assigning the %PATH% variable to a temporary variable and echoing but I saw the duplications there as well.
I saw in some stack answer that the %PATH% variable we use in the batch file is actually a concatenation of both User Path and System Path.
At the Command Prompt, I tried:
REG QUERY "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v PATH"
but I don't have idea much about whether we can use it to take that PATH value and assign to another variable.
So I need to find a way to assign ONLY the SYSTEM PATH to a temporary variable, let's say SYS_PATHS. How can I do that?
Is there a better way to overcome this scenario?
I found the answer to the question I asked in a link provided by #Mofi. This is how you can take the system path only, and append a directory to it.
set "env=HKLM\System\CurrentControlSet\Control\Session Manager\Environment"
for /f "tokens=2*" %%I in (
'reg query "%env%" /v Path ^| findstr /i "\<Path\>"'
) do setx /m PATH "%%J;%CD%"

Windows check string contains another not working

I have this batch file to append a environment variable if not exists
setLocal EnableDelayedExpansion
set echo off
set envPath=%PATH%
set comPath=";D:\Package\Libraries\Lib"
if x%envPath:comPath=%==x%envPath% (
setx PATH "%PATH%;D:\Package\Libraries\Lib" /M
)
pause
But its not working and says file was unexpected this time
I wrote based on Batch file: Find if substring is in string (not in a file)
As mentioned in the above comment, use delayed expansion in the main string, and regular expansion in the replace string. Run this batch as Admin from shortcut or from Admin Cmd Prompt:
#echo off
setLocal EnableDelayedExpansion
set "comPath=D:\Package\Libraries\Lib"
set "envPath=%PATH%" & set "Separator="
if not "%envPath:~-1%" == ";" set "Separator=;"
if "!envPath:%comPath%=!"=="%envPath%" (
setx PATH "%PATH%%Separator%%comPath%" /M )
timeout 5
exit /b
Note that updated PATH will be re-read from Registry only upon Cmd restart. If you need to use the amended PATH in the same batch, use SET instead of SETX to set the PATH temporarily for that Cmd session.
In a similar construct, if your extra path comPath is set inside IF or FOR loop, use call set "PATH=%%envPath:!comPath!=%%" instead.

Remove unwanted path name from %path% variable via batch

Scope: Windows XP or newer
Tools: Batch script
I need to be able to remove an unneeded path name from the system %PATH% variable. I know how to add a new path name to the system %PATH% variable, using a tool such as SETX.EXE, which also makes it immediately available within the existing CMD environment. It's probably a matter of using FIND and/or a FOR loop of some kind, but I'm not quite sure how to accomplish this. Here's a sample path statement...
%PATH% = C:\;C:\Program Files\Common Files\Java;C:\oracle\product\10.2.0\bin;C:\WINDOWS;C:\WINDOWS\system32;
From this, I need to be able to remove the full path name related to "oracle." So, in the above example, I need to be able to remove the "C:\oracle\product\10.2.0\bin" from the above path statement. Unfortunately, not only could the oracle path name be different than shown above, there could be multiple oracle path names and all need to be removed. I tried implementing the solution here...
How can I extract a full path from the PATH environment variable?
However, it just isn't working. The script wouldn't find the path name. Any help would be appreciated. Thank you.
This removes the substring C:\Program Files (x86)\Git\bin; from the PATH string and re-assigns:
set PATH=%PATH:C:\Program Files (x86)\Git\bin;=%
You might use this to see the change:
echo %PATH:C:\Program Files (x86)\Git\bin;=% | tr ; \n
Note: be exact on the substring. It's case-sensitive and slash-sensitive.
If you need to make it a persistent change use setx instead of set and open another console for changes to take effect.
setx /M PATH "%PATH:C:\Program Files (x86)\Git\bin;=%"
You can try something like this :
#echo off&cls
setlocal EnableDelayedExpansion
set $line=%path%
set $line=%$line: =#%
set $line=%$line:;= %
for %%a in (%$line%) do echo %%a | find /i "oracle" || set $newpath=!$newpath!;%%a
set $newpath=!$newpath:#= !
echo set path=!$newpath:~1!
I putted an echo to the last line. Check the result and If it's OK for you, remove it.
After trying SachaDee's answers I got errors with paths like
C:\Program Files (x86)
with brackets:
Program Files (x86)\Directory
gave me
Directorywas unexpected at this time. (no matter what time I tried it)
I added
set $line=%$line:)=^^)%
before the for-loop and
set $newpath=!$newpath:^^=!
after the loop (not sure if it is necessary)
#echo off
setlocal EnableDelayedExpansion
set path
set $line=%path%
set $line=%$line: =#%
set $line=%$line:;= %
set $line=%$line:)=^^)%
for %%a in (%$line%) do echo %%a | find /i "oracle" || set $newpath=!$newpath!;%%a
set $newpath=!$newpath:#= !
set $newpath=!$newpath:^^=!
set path=!$newpath:~1!
And it is now working.
I found the other solutions to this problem a bit awkward, I don't really want to rely on exact paths, complex 'delayed expansion' syntax, removing spaces for the 'for /f' loop and then adding them back in...
I think this is more elegant, and I commented the hell out of it so even someone new to the horrors of Batch can follow along.
::Turn off command display and allows environmental variables to be overridden for the current session
#echo off & setlocal
::Creates a unique file to use for the 'for loop'
set "TMPFILE="%temp%\tmp%RANDOM%%RANDOM%.txt""
::Duplicate PATH into OLDPATH
set "OLDPATH=%PATH%"
::Declare label for the 'goto' command
:Loop
::Extract the first text token with the default delimiter of semicolon
for /f "tokens=1 delims=;" %%G in ("%OLDPATH%") do (
REM Copy text token to TMPFILE unless what we want to remove is found
<NUL set /p="%%G" | find /i "StRiNgThAtMaTcHeSwHaTtOrEmOvE" >NUL 2>&1 || <NUL set /p="%%G;" >>%TMPFILE%
REM Remove text token from OLDPATH
set "OLDPATH=%OLDPATH:*;=%"
)
::Repeat loop until OLDPATH no longer has any delimiters, and then add any remaining value to TMPFILE
echo %OLDPATH% | findstr /C:";" >NUL && (goto :Loop) || <NUL set /p="%OLDPATH%" >>%TMPFILE%
::Set the path to TMPFILE
for /f "usebackq delims=" %%G in (%TMPFILE%) do (set "PATH=%%G")
::Clean-up
del %TMPFILE% >NUL 2>&1
::An echo and pause just for debug purposes
echo %PATH%
pause
I use this in CYGWIN to filter out CYGWIN paths before starting some Windows commands:
export PATH=`perl -e '#a=grep {$_ =~ /^\/cygdrive\//} split(":", $ENV{PATH});print join(":",#a)'`
I'm quite sure it's easy to adapt to Windows-native perl and bat files. Advantage: the flexible power of regular expressions.
I wanted to remove %LocalAppData%\Microsoft\WindowsApps; from PATH. But this was not possible due to using a another variable in the environment variable for Windows. The CALL hack is worked in SS64. (Also, thanks to Jens A. Koch for the base command.)
CALL set PATH=%PATH:%LocalAppData%\Microsoft\WindowsApps;=%
Of course, the PATH changing by SET will not be permanent. For fixed change, it is necessary to use the SETX command or directly change the entries in the Registry.
Actually, this solution was not needed to delete %LocalAppData%\Microsoft\WindowsApps; from PATH.
The %LocalAppData%\Microsoft\WindowsApps; is stored in the PATH entry of the Registry's HKCU\Environment key. Although it is more practical to delete this entry with the REG DELETE command, if there are another directories in the PATH entry, they will also be deleted, so new solution is needed.
I failed to remove the %USERPROFILE% variable syntax from SET (The %% symbol dilemma). Fortunately, PShell came to the rescue:
SET userprofile=
Powershell -c "$UserEnvironmentPath = [System.Environment]::GetEnvironmentVariable('Path', 'User'); $UserEnvironmentPath = $UserEnvironmentPath.Replace('%USERPROFILE%\AppData\Local\Microsoft\WindowsApps;',''); [Microsoft.Win32.Registry]::SetValue('HKEY_CURRENT_USER\Environment', 'Path', $UserEnvironmentPath, [Microsoft.Win32.RegistryValueKind]::ExpandString)"
Special thanks to vonpryz for the last command. Because PowerShell's [System.Environment]::SetEnvironmentVariable command saves variables to Registry as REG_SZ even if their original value type is REG_EXPAND_SZ, which it's the known issue.
I wrote this code to simply remove any python executeable path from the path variable,
and insert my own specefic python version in the path so i can run python with
the versoin i wanted.
setlocal enableDelayedExpansion
set path`enter code here`
set $line=%path%
set $line=%$line: =#%
set $line=%$line:;= %
set $line=%$line:)=^^)%
set newpath=
for %%a in (%$line%) do (
echo %%a | find /i "python" ||set newpath=!newpath!;%%a
)
set path=!newpath!
set PATH=D:\python2.7\;%PATH%
#REM Rest of your script
python --version
#REM to exit the batch but not the window
exit /b
also, the first line is important! don't remove it or it wont work.
Notice: this code must run from a batch ".bat" file , if u want to copy paste this code in cmd window, you must replace all "%%a" to "%a" in this code.
If you know a file that exists within the directory you want to remove (e.g. want to remove all paths that might include java.exe), the following will work very straightforwardly by simply doing string replacement, no need to parse the path, etc:
#REM Executable to look for
set CMD=java.exe
:search
#REM Find the executable anywhere in the path
for %%a in (%CMD%) do set FOUND=%%~$PATH:a
if "%FOUND%"=="" goto done
#REM Strip \cmd.ext so we just have the directory
set FOUND=!FOUND:\%CMD%=!
#echo Found %CMD% in %FOUND%
#echo Removing %FOUND% from path...
set "PATH=!PATH:%FOUND%=!"
#REM Clean up any lone leftover \ in the path (in case the path was C:\foo\ instead of C:\foo)
set PATH=%PATH:;\;=;%
goto search
:done

batch File -How to check if path to a bin folder is set

I my batch file i want to check if path to the following location is set
C:\Program Files(x86)\Windows Installer XML v3.5\bin
in any of the variable either in system variable or user defined variable
my need is to use content of the bin folder ; what if the user has not installed the way quoted above but has done something like
C:\WindowsinstallerXML\bin
or
D:\WindowsInstaller\bin
If you want to check every defined variable for the string, this would be the way. If you want to specifically check the path variable replacing set with echo %path% would work too.
set | find "C:\Program Files(x86)\Windows Installer XML v3.5\bin" > NUL 2>&1 || goto badinstall
If you want to check the install directory, I suggest checking to see if there is a registry value for it, if there is you can pull it like this.
for /f "tokens=3 delims= " %%a in ('reg query \HKCU\path\to\subkey\here /v "keyhere" ^| findstr /C:"keyhere"') do set wixmlpath=%%a
You can use:
PATH="C:\Program Files(x86)\Windows Installer XML v3.5\bin";%PATH%
Basically, instead of checking if it is set, why not to set explicitly in your script ?
#echo off
set input=%1
IF DEFINED input (ECHO you entered %input%) ELSE (ECHO usage: script bin_file_path)
If you know the name of one of the binary files, then you can use a FOR variable ~PATH: modifier to check if the path to that binary is currently in your PATH. And it will give you the actual path :)
for %F in (someFile.exe) do #if "%~$path:F" neq "" echo %~$path:F
If you want to use the code in a batch file, then each % must be doubled as %%.

Resources