【问题标题】:Remove unwanted path name from %path% variable via batch通过批处理从 %path% 变量中删除不需要的路径名
【发布时间】:2014-02-12 21:56:34
【问题描述】:

适用范围:Windows XP 或更新版本 工具:批处理脚本

我需要能够从系统 %PATH% 变量中删除不需要的路径名。我知道如何使用诸如 SETX.EXE 之类的工具将新路径名添加到系统 %PATH% 变量中,这也使其在现有 CMD 环境中立即可用。这可能是使用 FIND 和/或某种 FOR 循环的问题,但我不太确定如何完成此操作。这是一个示例路径语句...

%PATH% = C:\;C:\Program Files\Common Files\Java;C:\oracle\product\10.2.0\bin;C:\WINDOWS;C:\WINDOWS\system32;

由此,我需要能够删除与“oracle”相关的完整路径名。因此,在上面的示例中,我需要能够从上面的路径语句中删除“C:\oracle\product\10.2.0\bin”。不幸的是,不仅 oracle 路径名可能与上面显示的不同,而且可能有多个 oracle 路径名并且都需要删除。我尝试在这里实施解决方案...

How can I extract a full path from the PATH environment variable?

但是,它只是不起作用。脚本找不到路径名。任何帮助,将不胜感激。谢谢。

【问题讨论】:

    标签: windows batch-file path


    【解决方案1】:

    这会从 PATH 字符串中删除子字符串 C:\Program Files (x86)\Git\bin; 并重新分配:

    set PATH=%PATH:C:\Program Files (x86)\Git\bin;=%
    

    您可以使用它来查看更改:

    echo %PATH:C:\Program Files (x86)\Git\bin;=% | tr ; \n
    

    注意:准确的子字符串。它区分大小写和斜杠。

    如果您需要对其进行持久更改,请使用 setx 而不是 set 并打开另一个控制台以使更改生效。

    setx /M PATH "%PATH:C:\Program Files (x86)\Git\bin;=%"
    

    【讨论】:

    • 完美满足我的需要!
    • 使用setx 而不是set 会导致ERROR: Invalid syntax. Default option is not allowed more than '2' time(s). Type "SETX /?" for usage.
    • 只需加引号:setx /M PATH "%PATH:C:\Program Files (x86)\Git\bin;=%"
    • 对我来说,它删除了子字符串之后的所有路径:(
    • 语法参考在这里(ss64.com/nt/syntax-replace.html)
    【解决方案2】:

    你可以试试这样的:

    @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!
    

    我在最后一行添加了echo。检查结果,如果对您来说没问题,请将其删除。

    【讨论】:

    • 等待...仅适用于当前用户会话。我尝试使用带有 -m 选项的 setx 在系统范围内分配路径语句,但无济于事。即使回显显示正确的路径,当设置它而不是回显它时,它仍然只显示它。当我回显 %path% 时,它仍然显示原始的、未修改的系统路径。还有其他想法吗?谢谢。
    • 试试这样:reg.exe ADD "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v Path /t REG_EXPAND_SZ /d !newpath! /f
    • 用我的路径导致设置路径=“/f”。我像这样重新排序并修复了变量名:reg.exe ADD "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v Path /t REG_EXPAND_SZ /f /d "!$newpath:~1!"。对我来说它仍然不起作用,所以我添加了这个reg.exe ADD "HKEY_CURRENT_USER\Environment" /v Path /t REG_EXPAND_SZ /f /d "!$newpath:~1!"。这在注销并重新打开后有效。不知道为什么 SETX 在这里对我们中的一些人不起作用,我怀疑在我的情况下,因为路径很长。
    • 这是一个长度限制。见superuser.com/questions/387619/… ,我发现powershell 解决方案运行良好。
    【解决方案3】:

    在尝试了 SachaDee 的答案后,我遇到了类似路径的错误

    C:\Program Files (x86)
    

    带括号: Program Files (x86)\Directory 给了我

    目录was unexpected at this time.(不管我什么时候尝试过)

    我加了

    set $line=%$line:)=^^)%
    

    在for循环之前

    set $newpath=!$newpath:^^=!
    

    循环之后(不确定是否有必要)

    @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!
    

    现在它正在工作。

    【讨论】:

    • 我发现我必须添加另一个更改才能使更改持续到调用 shell。由于没有endlocal,因此脚本退出时对路径变量的更改会丢失。如果这不是您想要的,请将最后一行更改为:endlocal & set path=%$newpath:~1% 请注意,它必须在一行上,并且它使用% 而不是!。
    • 这是一个有效的方法!有没有办法抑制控制台输出?例如我将所有匹配项输出到控制台...
    • @SkyWalker 即使@echo off?您是否尝试将 >nul 添加到导致输出的行中?
    【解决方案4】:

    我发现这个问题的其他解决方案有点尴尬,我真的不想依赖精确路径、复杂的“延迟扩展”语法、删除“for /f”循环的空格,然后将它们添加回...

    我认为这更优雅,我对此进行了评论,因此即使是刚接触 Batch 恐怖的人也可以跟进。

    ::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
    

    【讨论】:

    • NUL 到底是如何工作的?为漂亮的代码 +1,谢谢。
    【解决方案5】:

    我在 CYGWIN 中使用它在启动一些 Windows 命令之前过滤掉 CYGWIN 路径:

    export PATH=`perl -e '@a=grep {$_ =~ /^\/cygdrive\//} split(":", $ENV{PATH});print join(":",@a)'`
    

    我很确定它很容易适应 Windows 原生 perl 和 bat 文件。优点:正则表达式的灵活性。

    【讨论】:

      【解决方案6】:

      我想从PATH 中删除%LocalAppData%\Microsoft\WindowsApps;。但这是不可能的,因为在 Windows 的环境变量中使用了另一个变量。 CALL hack 在 SS64 中工作。 (另外,感谢 Jens A. Koch 的基本命令。)

      CALL set PATH=%PATH:%LocalAppData%\Microsoft\WindowsApps;=%
      

      当然,PATH 更改为 SET 不会是永久性的。对于固定更改,需要使用SETX命令或直接更改注册表中的条目。

      实际上,从PATH 中删除%LocalAppData%\Microsoft\WindowsApps; 不需要此解决方案。

      %LocalAppData%\Microsoft\WindowsApps; 存储在注册表的HKCU\Environment 键的PATH 条目中。虽然用REG DELETE命令删除这个条目比较实用,但是如果PATH条目中还有其他目录也会被删除,所以需要新的解决方案。

      我未能从SET 中删除%USERPROFILE% 变量语法(%% 符号困境)。幸运的是,PShell 来救援了:

      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)"

      特别感谢vonpryz 提供last command。因为PowerShell的[System.Environment]::SetEnvironmentVariable命令将变量保存到注册表中为REG_SZ,即使它们的原始值类型是REG_EXPAND_SZ,也就是the known issue。

      【讨论】:

        【解决方案7】:

        我编写这段代码只是为了从路径变量中删除任何 python 可执行路径, 并在路径中插入我自己的特定 python 版本,以便我可以运行 python 我想要的版本。

        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
        

        另外,第一行很重要!不要删除它,否则它不会工作。

        注意:此代码必须从批处理“.bat”文件中运行,如果您想将这段代码复制粘贴到cmd窗口中,您必须将这段代码中的所有“%%a”替换为“%a”。

        【讨论】:

          【解决方案8】:

          如果您知道要删除的目录中存在的文件(例如,要删除可能包含java.exe 的所有路径),则只需进行字符串替换即可非常简单地执行以下操作,无需解析路径等:

          @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
          

          【讨论】:

            猜你喜欢
            • 2018-01-01
            • 1970-01-01
            • 2012-07-23
            • 2015-12-07
            • 1970-01-01
            • 2011-03-05
            • 1970-01-01
            • 1970-01-01
            • 2017-12-14
            相关资源
            最近更新 更多